"undefined method `stream'" when trying to use the `:pg_streaming` plugin
smaximov opened this issue · comments
Describe the bug
With the combined setup from these guides I get an "undefined method `stream'" error raised on the dataset when I invoke Relation#stream_each
. It works if :pg_streaming
was enabled explicitly on the Sequel database object though, so I guess it has something to do with the event configuration.gateway.connected
not being fired after the plugin is enabled. Or is my setup wrong?
cc @ianks.
To Reproduce
Run this script (optionally setting the DATABASE_URL
environment variable to point to an existing PostgreSQL database):
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'rom', '5.2.6'
gem 'rom-sql', '3.3.2'
gem 'pg', '1.2.3'
gem 'sequel', '5.41.0'
gem 'sequel_pg', '1.14.0', require: false
gem 'rspec', require: 'rspec/autorun'
end
DATABASE_URL = ENV['DATABASE_URL'] || 'postgres:///streaming_issue'
RSpec.describe 'Postgres Streaming' do
let(:container) do
ROM.container(:sql, DATABASE_URL) do |config|
config.relation(:users) { schema(infer: true) }
require 'rom/plugins/relation/sql/postgres/streaming'
config.plugin(:sql, relations: :pg_streaming)
end
end
before do
gateway = container.gateways[:default]
migration = gateway.migration do
up do
drop_table? :users
create_table :users do
primary_key :id
column :name, :text, null: false
end
run "INSERT INTO users(name) VALUES ('John Doe');"
end
end
migration.apply(gateway.connection, :up)
end
context 'when :pg_streaming Sequel extension is not enabled explicitly' do
it 'yields users' do
expect { |blk| container.relations[:users].stream_each(&blk) }.to yield_control.once
end
end
context 'when :pg_streaming Sequel extension is enabled explicitly' do
before { container.gateways[:default].connection.extension(:pg_streaming) }
it 'yields users' do
expect { |blk| container.relations[:users].stream_each(&blk) }.to yield_control.once
end
end
end
Expected behavior
All tests pass.
Actual behavior
One test fails:
F.
Failures:
1) Postgres Streaming when :pg_streaming Sequel extension is not enabled explicitly yields users
Failure/Error: expect { |blk| container.relations[:users].stream_each(&blk) }.to yield_control.once
NoMethodError:
undefined method `stream' for #<#<Class:0x0000000003216c10>:0x000000000201c758>
# /home/smaximov/.gem/ruby/2.6.0/gems/rom-sql-3.3.2/lib/rom/plugins/relation/sql/postgres/streaming.rb:71:in `stream_each'
# ./streaming-issue.rb:50:in `block (4 levels) in <main>'
# ./streaming-issue.rb:50:in `block (3 levels) in <main>'
Finished in 0.11089 seconds (files took 0.05538 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./streaming-issue.rb:49 # Postgres Streaming when :pg_streaming Sequel extension is not enabled explicitly yields users
My environment
- Affects my production application: NO
- Ruby version: 2.6.6
- OS: NixOS 20.09 (Linux 5.4.85 x86_64)
You need to require it before setting up the container, in your spec it's just too late
You need to require it before setting up the container
I actually had a similar thought yesterday, so I tried something like this, but it also didn't work:
let(:container) do
config = ROM::Configuration.new(:sql, DATABASE_URL)
require 'rom/plugins/relation/sql/postgres/streaming'
config.plugin(:sql, relations: :pg_streaming)
config.relation(:users) { schema(infer: true) }
ROM.container(config)
end
...so I guessed it wasn't the issue.
So now I moved the require before the config object instantiation and can confirm that it's working. It works as well if I move the require right before ROM.container
call when using the implicit config instantiation form, of course.
Thank you!