rom-rb / rom-sql

SQL support for rom-rb

Home Page:https://rom-rb.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

"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!