Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accidental replacement of main DB model connections in multi-database env #97

Open
kaorukobo opened this issue Feb 20, 2024 · 1 comment · May be fixed by #98
Open

Accidental replacement of main DB model connections in multi-database env #97

kaorukobo opened this issue Feb 20, 2024 · 1 comment · May be fixed by #98

Comments

@kaorukobo
Copy link

Note: I will make a pull request that follows this issue.

Summary

When we use DatabaseCleaner for a multi-database environment, the connection for "main" models (i.e., models inheriting the connection pool from ActiveRecord::Base) gets replaced with the connection for non-main models.

Reproduction

For the full reproduction code, see https://gist.github.com/kaorukobo/8dd0e5ef6c8662cc5de88aceea5043a1

setcwd_to_tmpdir
load_gems
create_config_database_yml
setup_activerecord

# defines Foo model, which use the connection pool from ApplicationRecord.
def define_foo_model
  eval(<<~RUBY, TOPLEVEL_BINDING)
    class Foo < ApplicationRecord
      connection.exec_query "CREATE TABLE foos (id INTEGER PRIMARY KEY)"
      reset_column_information
    end
  RUBY
end

# defines Bar model, which connects to alternate DB to be cleaned by DatabaseCleaner.
def define_bar_model
  eval(<<~RUBY, TOPLEVEL_BINDING)
    class Bar < ApplicationRecord
      establish_connection :bar
      connection.exec_query "CREATE TABLE bars (id INTEGER PRIMARY KEY)"
      reset_column_information
    end
  RUBY
end

RSpec.describe do
  it "works" do
    define_foo_model

    expect(Foo.connection.tables).to eq(["foos"])

    cleaner = DatabaseCleaner::Cleaners.new
    cleaner[:active_record, :db => :bar].strategy = :truncation
    cleaner.clean

    # define Bar model after `cleaner.clean`
    define_bar_model

    # Foo.connection gets replaced with Bar's connection!
    #
    # expected: ["foos"]
    #      got: ["bars"]
    expect(Foo.connection.tables).to eq(["foos"])
  end
end
@BoutPure
Copy link

Got this error too. After specifying cleaners for primary (AR::Base) and then to secondary (some other model) DB I got AR::Base connection to wrong DB

Quick workaround is to specify cleaning strategy for primary DB to be the last:

    DatabaseCleaner[:active_record, db: :secondary].strategy = :transaction
    DatabaseCleaner[:active_record, db: :primary].strategy = :transaction

This will return primary DB connection to ActiveRecord::Base

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants