diff --git a/lib/active_record_doctor/detectors/missing_presence_validation.rb b/lib/active_record_doctor/detectors/missing_presence_validation.rb index 9f4bd9e..4924116 100644 --- a/lib/active_record_doctor/detectors/missing_presence_validation.rb +++ b/lib/active_record_doctor/detectors/missing_presence_validation.rb @@ -30,6 +30,7 @@ def detect each_attribute(model, except: config(:ignore_attributes)) do |column| next unless validator_needed?(model, column) next if validator_present?(model, column) + next if counter_cache_column?(model, column) problem!(column: column.name, model: model.name) end @@ -94,6 +95,12 @@ def presence_validator_present?(model, column) def inclusion_validator_items(validator) validator.options[:in] || validator.options[:within] || [] end + + def counter_cache_column?(model, column) + model.reflect_on_all_associations(:has_many).any? do |reflection| + reflection.has_cached_counter? && reflection.counter_cache_column == column.name + end + end end end end diff --git a/test/active_record_doctor/detectors/missing_presence_validation_test.rb b/test/active_record_doctor/detectors/missing_presence_validation_test.rb index 99d0c76..110ab52 100644 --- a/test/active_record_doctor/detectors/missing_presence_validation_test.rb +++ b/test/active_record_doctor/detectors/missing_presence_validation_test.rb @@ -139,6 +139,38 @@ def test_timestamps_are_not_reported refute_problems end + def test_counter_caches_are_not_reported + Context.create_table(:companies) do |t| + t.integer :users_count, default: 0, null: false + end.define_model do + has_many :users + end + + Context.create_table(:users) do |t| + t.integer :company_id + end.define_model do + belongs_to :company, counter_cache: true + end + + refute_problems + end + + def test_counter_caches_with_custom_names_are_not_reported + Context.create_table(:companies) do |t| + t.integer :custom_users_count, default: 0, null: false + end.define_model do + has_many :users, counter_cache: :custom_users_count + end + + Context.create_table(:users) do |t| + t.integer :company_id + end.define_model do + belongs_to :company, counter_cache: :custom_users_count + end + + refute_problems + end + def test_models_with_non_existent_tables_are_skipped Context.define_model(:User)