Accidental replacement of main DB model connections in multi-database env
kaorukobo opened this issue · 2 comments
kaorukobo commented
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 commented
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