diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index aeb15d1..9a406c5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -52,6 +52,8 @@ jobs: gemfile: 'gemfiles/ar_6_1.gemfile' - ruby-version: '3.2' gemfile: 'gemfiles/ar_7_0.gemfile' + - ruby-version: '3.2' + gemfile: 'gemfiles/ar_7_1.gemfile' - ruby-version: 'head' gemfile: 'gemfiles/ar_main.gemfile' diff --git a/gemfiles/ar_7_1.gemfile b/gemfiles/ar_7_1.gemfile new file mode 100644 index 0000000..7ac21e5 --- /dev/null +++ b/gemfiles/ar_7_1.gemfile @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' + +gem 'activerecord', '~> 7.1.0' + +gemspec path: '../' diff --git a/lib/database_consistency.rb b/lib/database_consistency.rb index 587de1d..8767d92 100644 --- a/lib/database_consistency.rb +++ b/lib/database_consistency.rb @@ -81,7 +81,7 @@ require 'database_consistency/checkers/column_checkers/primary_key_type_checker' require 'database_consistency/checkers/column_checkers/enum_value_checker' require 'database_consistency/checkers/column_checkers/three_state_boolean_checker' -require 'database_consistency/checkers/column_checkers/implicit_ordering_checker.rb' +require 'database_consistency/checkers/column_checkers/implicit_ordering_checker' require 'database_consistency/checkers/validator_checkers/validator_checker' require 'database_consistency/checkers/validator_checkers/missing_unique_index_checker' diff --git a/lib/database_consistency/checkers/validators_fraction_checkers/column_presence_checker.rb b/lib/database_consistency/checkers/validators_fraction_checkers/column_presence_checker.rb index f54683b..dd57404 100644 --- a/lib/database_consistency/checkers/validators_fraction_checkers/column_presence_checker.rb +++ b/lib/database_consistency/checkers/validators_fraction_checkers/column_presence_checker.rb @@ -34,7 +34,23 @@ def report_template(status, column_name:, error_slug: nil) end def weak_option? - validators.all? { |validator| validator.options.slice(*WEAK_OPTIONS).any? } + validators.all? do |validator| + result = validator.options.slice(*WEAK_OPTIONS).any? + + result = false if required_with_if?(validator) + + result + end + end + + def belongs_to_required_validates_foreign_key_disabled? + ActiveRecord.version >= Gem::Version.new('7.1.0') && + !ActiveRecord.belongs_to_required_validates_foreign_key + end + + def required_with_if?(validator) + belongs_to_required_validates_foreign_key_disabled? && + validator.options[:message] == :required && validator.options[:if].present? end def check diff --git a/spec/checkers/column_presence_checker_spec.rb b/spec/checkers/column_presence_checker_spec.rb index 832f2e9..8f30b64 100644 --- a/spec/checkers/column_presence_checker_spec.rb +++ b/spec/checkers/column_presence_checker_spec.rb @@ -158,6 +158,26 @@ context 'when `belongs_to` is required' do let(:klass) { define_class { |klass| klass.belongs_to :user, **required } } + if ActiveRecord.version >= Gem::Version.new('7.1.0') + context 'when belongs_to_required_validates_foreign_key is set to false' do + specify do + old = ActiveRecord.belongs_to_required_validates_foreign_key + ActiveRecord.belongs_to_required_validates_foreign_key = false + + expect(checker.report.first).to have_attributes( + checker_name: 'ColumnPresenceChecker', + table_or_model_name: klass.name, + column_or_attribute_name: 'user', + status: :fail, + error_message: nil, + error_slug: :association_missing_null_constraint + ) + + ActiveRecord.belongs_to_required_validates_foreign_key = old + end + end + end + specify do expect(checker.report.first).to have_attributes( checker_name: 'ColumnPresenceChecker', @@ -199,11 +219,44 @@ error_slug: nil ) end + + if ActiveRecord.version >= Gem::Version.new('7.1.0') + context 'when belongs_to_required_validates_foreign_key is set to true' do + specify do + old = ActiveRecord.belongs_to_required_validates_foreign_key + ActiveRecord.belongs_to_required_validates_foreign_key = true + + expect(checker.report.first).to have_attributes( + checker_name: 'ColumnPresenceChecker', + table_or_model_name: klass.name, + column_or_attribute_name: 'user', + status: :ok, + error_message: nil, + error_slug: nil + ) + + ActiveRecord.belongs_to_required_validates_foreign_key = old + end + end + end end context 'when `belongs_to` is optional' do let(:klass) { define_class { |klass| klass.belongs_to :user, **optional } } + if ActiveRecord.version >= Gem::Version.new('7.1.0') + context 'when belongs_to_required_validates_foreign_key is set to false' do + specify do + old = ActiveRecord.belongs_to_required_validates_foreign_key + ActiveRecord.belongs_to_required_validates_foreign_key = false + + expect(checker.report).to be_nil + + ActiveRecord.belongs_to_required_validates_foreign_key = old + end + end + end + specify do expect(checker.report).to be_nil end