Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@

source "https://rubygems.org"
gemspec

# minitest 6.0 removed run_one_method which minitest-fork_executor depends on
gem "minitest", "~> 5.0"
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,16 @@ ActiveRecordDoctor.configure do
end
```

### Multiple Databases

`active_record_doctor` currently only analyzes models connected to the primary
database. Models that use a different database connection — whether via
`establish_connection`, `connects_to`, or by inheriting from an abstract class
with its own connection — are automatically skipped by all detectors.

This means that if you have gems or parts of your application that connect to a
secondary database, their models won't be checked and won't cause errors.

### Indexing Unindexed Foreign Keys

Foreign keys should be indexed unless it's proven ineffective. However, Rails
Expand Down
5 changes: 4 additions & 1 deletion lib/active_record_doctor/detectors/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,10 @@ def check_constraints(table_name)
end

def models
ActiveRecord::Base.descendants.sort_by(&:name)
base_pool = ActiveRecord::Base.connection_pool
ActiveRecord::Base.descendants
.reject { |model| model.connection_pool != base_pool }
.sort_by(&:name)
end

def underscored_name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,4 +349,17 @@ def test_created_on_updated_on_with_null_are_disallowed
add `NOT NULL` to users.updated_on - timestamp columns are set automatically by Active Record and allowing NULL may lead to inconsistencies introduced by bulk operations
OUTPUT
end

def test_models_with_non_primary_connection_are_skipped
# Models connected to a secondary database should be silently skipped.
# Previously this would crash with e.g. PG::UndefinedTable when the
# secondary table didn't exist in the primary database (see #149).
SecondaryContext.create_table(:users) do |t|
t.string :name, null: true
end.define_model do
validates :name, presence: true
end

refute_problems
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,12 @@ def test_global_ignore_tables

refute_problems
end

def test_models_with_non_primary_connection_are_skipped
# Models connected to a secondary database should be silently skipped,
# not reported as referencing undefined tables (see #149).
SecondaryContext.create_table(:users).define_model

refute_problems
end
end
10 changes: 7 additions & 3 deletions test/setup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@

require "logger"
require "active_record"
require "pg"
require "mysql2"
require "sqlite3"
%w[pg mysql2 sqlite3].each do |adapter_gem|
require adapter_gem
rescue LoadError
# Not all adapters need to be installed; only the one matching DATABASE_ADAPTER is required.
end

adapter = ENV.fetch("DATABASE_ADAPTER")

Expand Down Expand Up @@ -91,6 +93,8 @@ class SecondaryRecord < ApplicationRecord

SecondaryRecord.establish_connection :secondary

SecondaryContext = TransientRecord.context_for SecondaryRecord

if ActiveRecord.version >= Gem::Version.new("7.1")
# See https://github.com/rails/rails/pull/46522 for details.
# When `false` (default in Rails 7.1) - validate presence only when the foreign key changed.
Expand Down