From a9db5f52d18e0458694ee38950c78c639ea6cd50 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Thu, 22 Aug 2024 16:53:32 +0200 Subject: [PATCH 1/2] Update `Rails/Validation` specs to modern style --- spec/rubocop/cop/rails/validation_spec.rb | 325 +++++++++------------- 1 file changed, 137 insertions(+), 188 deletions(-) diff --git a/spec/rubocop/cop/rails/validation_spec.rb b/spec/rubocop/cop/rails/validation_spec.rb index 20f2fabea3..3aa2b891f9 100644 --- a/spec/rubocop/cop/rails/validation_spec.rb +++ b/spec/rubocop/cop/rails/validation_spec.rb @@ -1,225 +1,174 @@ # frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::Validation, :config do - it 'accepts new style validations' do - expect_no_offenses('validates :name') - end - - described_class::RESTRICT_ON_SEND.each_with_index do |validation, number| - it "registers an offense for #{validation}" do - offenses = inspect_source("#{validation} :name") - expect(offenses.first.message.include?(described_class::ALLOWLIST[number])).to be(true) + described_class::TYPES.each do |type| + it "registers an offense for with validates_#{type}_of" do + type = 'length' if type == 'size' + expect_offense(<<~RUBY, type: type) + validates_#{type}_of :full_name, :birth_date + ^^^^^^^^^^^{type}^^^ Prefer the new style validations `validates :column, #{type}: value` over `validates_#{type}_of`. + RUBY + + expect_correction(<<~RUBY) + validates :full_name, :birth_date, #{type}: true + RUBY end - end - describe '#autocorrect' do - shared_examples 'autocorrects' do - it 'autocorrects' do - expect(autocorrect_source(source)).to eq(autocorrected_source) - end - end + it "registers an offense for with validates_#{type}_of when method arguments are enclosed in parentheses" do + type = 'length' if type == 'size' + expect_offense(<<~RUBY, type: type) + validates_#{type}_of(:full_name, :birth_date) + ^^^^^^^^^^^{type}^^^ Prefer the new style validations `validates :column, #{type}: value` over `validates_#{type}_of`. + RUBY - shared_examples 'does not autocorrect' do - it 'does not autocorrect' do - expect(autocorrect_source(source)).to eq(source) - end + expect_correction(<<~RUBY) + validates(:full_name, :birth_date, #{type}: true) + RUBY end - described_class::TYPES.each do |type| - context "with validates_#{type}_of" do - let(:autocorrected_source) do - type = 'length' if type == 'size' - - "validates :full_name, :birth_date, #{type}: true" - end - - let(:source) do - "validates_#{type}_of :full_name, :birth_date" - end - - include_examples 'autocorrects' - end - - context "with validates_#{type}_of when method arguments are enclosed in parentheses" do - let(:autocorrected_source) do - type = 'length' if type == 'size' - - "validates(:full_name, :birth_date, #{type}: true)" - end - - let(:source) do - "validates_#{type}_of(:full_name, :birth_date)" - end - - include_examples 'autocorrects' - end - - context "with validates_#{type}_of when attributes are specified with array literal" do - let(:autocorrected_source) do - type = 'length' if type == 'size' - - "validates :full_name, :birth_date, #{type}: true" - end - - let(:source) do - "validates_#{type}_of [:full_name, :birth_date]" - end - - include_examples 'autocorrects' - end - - context "with validates_#{type}_of when attributes are specified with frozen array literal" do - let(:autocorrected_source) do - type = 'length' if type == 'size' - - "validates :full_name, :birth_date, #{type}: true" - end - - let(:source) do - "validates_#{type}_of [:full_name, :birth_date].freeze" - end - - include_examples 'autocorrects' - end - - context "with validates_#{type}_of when attributes are specified with symbol array literal" do - let(:autocorrected_source) do - type = 'length' if type == 'size' - - "validates :full_name, :birth_date, #{type}: true" - end - - let(:source) do - "validates_#{type}_of %i[full_name birth_date]" - end - - include_examples 'autocorrects' - end - - context "with validates_#{type}_of when attributes are specified with frozen symbol array literal" do - let(:autocorrected_source) do - type = 'length' if type == 'size' + it "registers an offense for with validates_#{type}_of when attributes are specified with array literal" do + type = 'length' if type == 'size' + expect_offense(<<~RUBY, type: type) + validates_#{type}_of [:full_name, :birth_date] + ^^^^^^^^^^^{type}^^^ Prefer the new style validations `validates :column, #{type}: value` over `validates_#{type}_of`. + RUBY - "validates :full_name, :birth_date, #{type}: true" - end - - let(:source) do - "validates_#{type}_of %i[full_name birth_date].freeze" - end - - include_examples 'autocorrects' - end + expect_correction(<<~RUBY) + validates :full_name, :birth_date, #{type}: true + RUBY end - context 'with single attribute name' do - let(:autocorrected_source) do - 'validates :a, numericality: true' - end - - let(:source) do - 'validates_numericality_of :a' - end + it "registers an offense for with validates_#{type}_of when attributes are specified with frozen array literal" do + type = 'length' if type == 'size' + expect_offense(<<~RUBY, type: type) + validates_#{type}_of [:full_name, :birth_date].freeze + ^^^^^^^^^^^{type}^^^ Prefer the new style validations `validates :column, #{type}: value` over `validates_#{type}_of`. + RUBY - include_examples 'autocorrects' + expect_correction(<<~RUBY) + validates :full_name, :birth_date, #{type}: true + RUBY end - context 'with multi attribute names' do - let(:autocorrected_source) do - 'validates :a, :b, numericality: true' - end + it "registers an offense for with validates_#{type}_of when attributes are specified with symbol array literal" do + type = 'length' if type == 'size' + expect_offense(<<~RUBY, type: type) + validates_#{type}_of %i[full_name birth_date] + ^^^^^^^^^^^{type}^^^ Prefer the new style validations `validates :column, #{type}: value` over `validates_#{type}_of`. + RUBY - let(:source) do - 'validates_numericality_of :a, :b' - end - - include_examples 'autocorrects' + expect_correction(<<~RUBY) + validates :full_name, :birth_date, #{type}: true + RUBY end - context 'with non-braced hash literal' do - let(:autocorrected_source) do - 'validates :a, :b, numericality: { minimum: 1 }' - end - - let(:source) do - 'validates_numericality_of :a, :b, minimum: 1' - end - - include_examples 'autocorrects' + it "registers an offense for with validates_#{type}_of when " \ + 'attributes are specified with frozen symbol array literal' do + type = 'length' if type == 'size' + expect_offense(<<~RUBY, type: type) + validates_#{type}_of %i[full_name birth_date].freeze + ^^^^^^^^^^^{type}^^^ Prefer the new style validations `validates :column, #{type}: value` over `validates_#{type}_of`. + RUBY + + expect_correction(<<~RUBY) + validates :full_name, :birth_date, #{type}: true + RUBY end + end - context 'with braced hash literal' do - let(:autocorrected_source) do - 'validates :a, :b, numericality: { minimum: 1 }' - end - - let(:source) do - 'validates_numericality_of :a, :b, { minimum: 1 }' - end + it 'registers an offense with single attribute name' do + expect_offense(<<~RUBY) + validates_numericality_of :a + ^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer the new style [...] + RUBY - include_examples 'autocorrects' - end + expect_correction(<<~RUBY) + validates :a, numericality: true + RUBY + end - context 'with a proc' do - let(:autocorrected_source) do - 'validates :a, :b, comparison: { greater_than: -> { Time.zone.today } }' - end + it 'registers an offense with multi attribute names' do + expect_offense(<<~RUBY) + validates_numericality_of :a, :b + ^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer the new style [...] + RUBY - let(:source) do - 'validates_comparison_of :a, :b, greater_than: -> { Time.zone.today }' - end + expect_correction(<<~RUBY) + validates :a, :b, numericality: true + RUBY + end - include_examples 'autocorrects' - end + it 'registers an offense with non-braced hash literal' do + expect_offense(<<~RUBY) + validates_numericality_of :a, :b, minimum: 1 + ^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer the new style [...] + RUBY - context 'with splat' do - let(:autocorrected_source) do - 'validates :a, *b, numericality: true' - end + expect_correction(<<~RUBY) + validates :a, :b, numericality: { minimum: 1 } + RUBY + end - let(:source) do - 'validates_numericality_of :a, *b' - end + it 'registers an offense with braced hash literal' do + expect_offense(<<~RUBY) + validates_numericality_of :a, :b, { minimum: 1 } + ^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer the new style [...] + RUBY - include_examples 'autocorrects' - end + expect_correction(<<~RUBY) + validates :a, :b, numericality: { minimum: 1 } + RUBY + end - context 'with splat and options' do - let(:autocorrected_source) do - 'validates :a, *b, :c, numericality: { minimum: 1 }' - end + it 'registers an offense with a proc' do + expect_offense(<<~RUBY) + validates_comparison_of :a, :b, greater_than: -> { Time.zone.today } + ^^^^^^^^^^^^^^^^^^^^^^^ Prefer the new style [...] + RUBY - let(:source) do - 'validates_numericality_of :a, *b, :c, minimum: 1' - end + expect_correction(<<~RUBY) + validates :a, :b, comparison: { greater_than: -> { Time.zone.today } } + RUBY + end - include_examples 'autocorrects' - end + it 'registers an offense with a splat' do + expect_offense(<<~RUBY) + validates_numericality_of :a, *b + ^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer the new style [...] + RUBY - context 'with trailing send node' do - let(:source) do - 'validates_numericality_of :a, b' - end + expect_correction(<<~RUBY) + validates :a, *b, numericality: true + RUBY + end - include_examples 'does not autocorrect' - end + it 'registers an offense with a splat and options' do + expect_offense(<<~RUBY) + validates_numericality_of :a, *b, :c, minimum: 1 + ^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer the new style [...] + RUBY - context 'with trailing constant' do - let(:source) do - 'validates_numericality_of :a, B' - end + expect_correction(<<~RUBY) + validates :a, *b, :c, numericality: { minimum: 1 } + RUBY + end - include_examples 'does not autocorrect' - end + it 'registers no offense with trailing send node' do + expect_no_offenses(<<~RUBY) + validates_numericality_of :a, b + RUBY + end - context 'with trailing local variable' do - let(:source) do - <<~RUBY - b = { minimum: 1 } - validates_numericality_of :a, b - RUBY - end + it 'registers no offense with trailing constant' do + expect_no_offenses(<<~RUBY) + validates_numericality_of :a, B + RUBY + end - include_examples 'does not autocorrect' - end + it 'registers no offense with trailing local variable' do + expect_no_offenses(<<~RUBY) + b = { minimum: 1 } + validates_numericality_of :a, b + RUBY end end From 5e2237a83ecd3b0277ec9e1ef96ee257af6681d5 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Thu, 22 Aug 2024 16:55:52 +0200 Subject: [PATCH 2/2] Fix an error for `Rails/Validation` when passing no arguments --- changelog/fix_error_rails_validation.md | 1 + lib/rubocop/cop/rails/validation.rb | 2 +- spec/rubocop/cop/rails/validation_spec.rb | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 changelog/fix_error_rails_validation.md diff --git a/changelog/fix_error_rails_validation.md b/changelog/fix_error_rails_validation.md new file mode 100644 index 0000000000..024d4bf8b9 --- /dev/null +++ b/changelog/fix_error_rails_validation.md @@ -0,0 +1 @@ +* [#1337](https://github.com/rubocop/rubocop-rails/pull/1337): Fix an error for `Rails/Validation` when passing no arguments. ([@earlopain][]) diff --git a/lib/rubocop/cop/rails/validation.rb b/lib/rubocop/cop/rails/validation.rb index beaa8f2b6e..bc78b01625 100644 --- a/lib/rubocop/cop/rails/validation.rb +++ b/lib/rubocop/cop/rails/validation.rb @@ -59,11 +59,11 @@ class Validation < Base def on_send(node) return if node.receiver + return unless (last_argument = node.last_argument) range = node.loc.selector add_offense(range, message: message(node)) do |corrector| - last_argument = node.last_argument return if !last_argument.literal? && !last_argument.splat_type? && !frozen_array_argument?(last_argument) corrector.replace(range, 'validates') diff --git a/spec/rubocop/cop/rails/validation_spec.rb b/spec/rubocop/cop/rails/validation_spec.rb index 3aa2b891f9..c178b371d3 100644 --- a/spec/rubocop/cop/rails/validation_spec.rb +++ b/spec/rubocop/cop/rails/validation_spec.rb @@ -171,4 +171,10 @@ validates_numericality_of :a, b RUBY end + + it 'registers no offense when no arguments are passed' do + expect_no_offenses(<<~RUBY) + validates_numericality_of + RUBY + end end