Skip to content

Commit d558b3c

Browse files
r7kamurakoic
authored andcommitted
Support more complex argument patterns on Rails/Validation auto-correction
1 parent 647dec0 commit d558b3c

File tree

2 files changed

+133
-32
lines changed

2 files changed

+133
-32
lines changed

lib/rubocop/cop/rails/validation.rb

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ def on_send(node)
5757
end
5858

5959
def autocorrect(node)
60+
last_argument = node.arguments.last
61+
return if !last_argument.literal? && !last_argument.splat_type?
62+
6063
lambda do |corrector|
6164
corrector.replace(node.loc.selector, 'validates')
6265
correct_validate_type(corrector, node)
@@ -75,12 +78,14 @@ def preferred_method(method)
7578
end
7679

7780
def correct_validate_type(corrector, node)
78-
options = node.arguments.find { |arg| !arg.sym_type? }
81+
last_argument = node.arguments.last
7982
validate_type = node.method_name.to_s.split('_')[1]
8083

81-
if options
82-
corrector.replace(options.loc.expression,
83-
"#{validate_type}: #{braced_options(options)}")
84+
if last_argument.hash_type?
85+
corrector.replace(
86+
last_argument.loc.expression,
87+
"#{validate_type}: #{braced_options(last_argument)}"
88+
)
8489
else
8590
corrector.insert_after(node.loc.expression,
8691
", #{validate_type}: true")

spec/rubocop/cop/rails/validation_spec.rb

Lines changed: 124 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,34 +20,130 @@
2020
end
2121
end
2222

23-
describe 'autocorrect' do
24-
described_class::TYPES.each do |parameter|
25-
it "corrects validates_#{parameter}_of" do
26-
new_source = autocorrect_source(
27-
"validates_#{parameter}_of :full_name, :birth_date"
28-
)
29-
expect(new_source).to eq(
30-
"validates :full_name, :birth_date, #{parameter}: true"
31-
)
32-
end
33-
end
34-
35-
it 'corrects validates_numericality_of with options' do
36-
new_source = autocorrect_source(
37-
'validates_numericality_of :age, minimum: 0, maximum: 122'
38-
)
39-
expect(new_source).to eq(
40-
'validates :age, numericality: { minimum: 0, maximum: 122 }'
41-
)
42-
end
43-
44-
it 'autocorrect validates_numericality_of with options in braces' do
45-
new_source = autocorrect_source(
46-
'validates_numericality_of :age, { minimum: 0, maximum: 122 }'
47-
)
48-
expect(new_source).to eq(
49-
'validates :age, numericality: { minimum: 0, maximum: 122 }'
50-
)
23+
describe '#autocorrect' do
24+
shared_examples 'auto-corrects' do
25+
it 'auto-corrects' do
26+
expect(autocorrect_source(source)).to eq(auto_corrected_source)
27+
end
28+
end
29+
30+
shared_examples 'does not auto-correct' do
31+
it 'does not auto-correct' do
32+
expect(autocorrect_source(source)).to eq(source)
33+
end
34+
end
35+
36+
described_class::TYPES.each do |type|
37+
context "with validates_#{type}_of" do
38+
let(:auto_corrected_source) do
39+
"validates :full_name, :birth_date, #{type}: true"
40+
end
41+
42+
let(:source) do
43+
"validates_#{type}_of :full_name, :birth_date"
44+
end
45+
46+
include_examples 'auto-corrects'
47+
end
48+
end
49+
50+
context 'with single attribute name' do
51+
let(:auto_corrected_source) do
52+
'validates :a, numericality: true'
53+
end
54+
55+
let(:source) do
56+
'validates_numericality_of :a'
57+
end
58+
59+
include_examples 'auto-corrects'
60+
end
61+
62+
context 'with multi attribute names' do
63+
let(:auto_corrected_source) do
64+
'validates :a, :b, numericality: true'
65+
end
66+
67+
let(:source) do
68+
'validates_numericality_of :a, :b'
69+
end
70+
71+
include_examples 'auto-corrects'
72+
end
73+
74+
context 'with non-braced hash literal' do
75+
let(:auto_corrected_source) do
76+
'validates :a, :b, numericality: { minimum: 1 }'
77+
end
78+
79+
let(:source) do
80+
'validates_numericality_of :a, :b, minimum: 1'
81+
end
82+
83+
include_examples 'auto-corrects'
84+
end
85+
86+
context 'with braced hash literal' do
87+
let(:auto_corrected_source) do
88+
'validates :a, :b, numericality: { minimum: 1 }'
89+
end
90+
91+
let(:source) do
92+
'validates_numericality_of :a, :b, { minimum: 1 }'
93+
end
94+
95+
include_examples 'auto-corrects'
96+
end
97+
98+
context 'with splat' do
99+
let(:auto_corrected_source) do
100+
'validates :a, *b, numericality: true'
101+
end
102+
103+
let(:source) do
104+
'validates_numericality_of :a, *b'
105+
end
106+
107+
include_examples 'auto-corrects'
108+
end
109+
110+
context 'with splat and options' do
111+
let(:auto_corrected_source) do
112+
'validates :a, *b, :c, numericality: { minimum: 1 }'
113+
end
114+
115+
let(:source) do
116+
'validates_numericality_of :a, *b, :c, minimum: 1'
117+
end
118+
119+
include_examples 'auto-corrects'
120+
end
121+
122+
context 'with trailing send node' do
123+
let(:source) do
124+
'validates_numericality_of :a, b'
125+
end
126+
127+
include_examples 'does not auto-correct'
128+
end
129+
130+
context 'with trailing constant' do
131+
let(:source) do
132+
'validates_numericality_of :a, B'
133+
end
134+
135+
include_examples 'does not auto-correct'
136+
end
137+
138+
context 'with trailing local variable' do
139+
let(:source) do
140+
<<-RUBY.strip_indent
141+
b = { minimum: 1 }
142+
validates_numericality_of :a, b
143+
RUBY
144+
end
145+
146+
include_examples 'does not auto-correct'
51147
end
52148
end
53149
end

0 commit comments

Comments
 (0)