Skip to content

Commit 7766c50

Browse files
authored
Merge pull request #119 from koic/fix_an_incorrect_autocorrect_for_rails_validation
[Fix #118] Fix an incorrect autocorrect for `Rails/Validation`
2 parents 5aa0e98 + 27004dd commit 7766c50

File tree

3 files changed

+102
-8
lines changed

3 files changed

+102
-8
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## master (unreleased)
44

5+
### Bug fixes
6+
7+
* [#118](https://github.com/rubocop-hq/rubocop-rails/issues/118): Fix an incorrect autocorrect for `Rails/Validation` when attributes are specified with array literal. ([@koic][])
8+
59
## 2.3.1 (2019-08-26)
610

711
### Bug fixes

lib/rubocop/cop/rails/validation.rb

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ def on_send(node)
6161

6262
def autocorrect(node)
6363
last_argument = node.arguments.last
64-
return if !last_argument.literal? && !last_argument.splat_type?
64+
return if !last_argument.literal? && !last_argument.splat_type? &&
65+
!frozen_array_argument?(last_argument)
6566

6667
lambda do |corrector|
6768
corrector.replace(node.loc.selector, 'validates')
@@ -81,19 +82,56 @@ def preferred_method(method)
8182
end
8283

8384
def correct_validate_type(corrector, node)
84-
last_argument = node.arguments.last
85-
validate_type = node.method_name.to_s.split('_')[1]
85+
last_argument = node.last_argument
8686

8787
if last_argument.hash_type?
88-
corrector.replace(
89-
last_argument.loc.expression,
90-
"#{validate_type}: #{braced_options(last_argument)}"
91-
)
88+
correct_validate_type_for_hash(corrector, node, last_argument)
89+
elsif last_argument.array_type?
90+
loc = last_argument.loc
91+
92+
correct_validate_type_for_array(corrector, node, last_argument, loc)
93+
elsif frozen_array_argument?(last_argument)
94+
arguments = node.last_argument.receiver
95+
loc = arguments.parent.loc
96+
97+
correct_validate_type_for_array(corrector, node, arguments, loc)
9298
else
9399
range = last_argument.source_range
94100

95-
corrector.insert_after(range, ", #{validate_type}: true")
101+
corrector.insert_after(range, ", #{validate_type(node)}: true")
102+
end
103+
end
104+
105+
def correct_validate_type_for_hash(corrector, node, arguments)
106+
corrector.replace(
107+
arguments.loc.expression,
108+
"#{validate_type(node)}: #{braced_options(arguments)}"
109+
)
110+
end
111+
112+
def correct_validate_type_for_array(corrector, node, arguments, loc)
113+
attributes = []
114+
115+
arguments.each_child_node do |child_node|
116+
attributes << if arguments.percent_literal?
117+
":#{child_node.source}"
118+
else
119+
child_node.source
120+
end
96121
end
122+
123+
corrector.replace(
124+
loc.expression,
125+
"#{attributes.join(', ')}, #{validate_type(node)}: true"
126+
)
127+
end
128+
129+
def validate_type(node)
130+
node.method_name.to_s.split('_')[1]
131+
end
132+
133+
def frozen_array_argument?(argument)
134+
argument.send_type? && argument.method?(:freeze)
97135
end
98136

99137
def braced_options(options)

spec/rubocop/cop/rails/validation_spec.rb

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,58 @@
5858

5959
include_examples 'auto-corrects'
6060
end
61+
62+
context "with validates_#{type}_of when " \
63+
'attributes are specified with array literal' do
64+
let(:auto_corrected_source) do
65+
"validates :full_name, :birth_date, #{type}: true"
66+
end
67+
68+
let(:source) do
69+
"validates_#{type}_of [:full_name, :birth_date]"
70+
end
71+
72+
include_examples 'auto-corrects'
73+
end
74+
75+
context "with validates_#{type}_of when " \
76+
'attributes are specified with frozen array literal' do
77+
let(:auto_corrected_source) do
78+
"validates :full_name, :birth_date, #{type}: true"
79+
end
80+
81+
let(:source) do
82+
"validates_#{type}_of [:full_name, :birth_date].freeze"
83+
end
84+
85+
include_examples 'auto-corrects'
86+
end
87+
88+
context "with validates_#{type}_of when " \
89+
'attributes are specified with symbol array literal' do
90+
let(:auto_corrected_source) do
91+
"validates :full_name, :birth_date, #{type}: true"
92+
end
93+
94+
let(:source) do
95+
"validates_#{type}_of %i[full_name birth_date]"
96+
end
97+
98+
include_examples 'auto-corrects'
99+
end
100+
101+
context "with validates_#{type}_of when " \
102+
'attributes are specified with frozen symbol array literal' do
103+
let(:auto_corrected_source) do
104+
"validates :full_name, :birth_date, #{type}: true"
105+
end
106+
107+
let(:source) do
108+
"validates_#{type}_of %i[full_name birth_date].freeze"
109+
end
110+
111+
include_examples 'auto-corrects'
112+
end
61113
end
62114

63115
context 'with single attribute name' do

0 commit comments

Comments
 (0)