Skip to content

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

@kaorukobo

Description

@kaorukobo

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions