Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support more complex argument patterns on Rails/Validation auto-correction #6689

Merged
merged 1 commit into from Jan 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -11,6 +11,7 @@
* [#6254](https://github.com/rubocop-hq/rubocop/issues/6254): Fix `Layout/RescueEnsureAlignment` for non-local assignments. ([@marcotc][])
* [#6648](https://github.com/rubocop-hq/rubocop/issues/6648): Fix auto-correction of `Style/EmptyLiteral` when `Hash.new` is passed as the first argument to `super`. ([@rrosenblum][])
* [#6351](https://github.com/rubocop-hq/rubocop/pull/6351): Fix a false positive for `Layout/ClosingParenthesisIndentation` when first argument is multiline. ([@antonzaytsev][])
* [#6689](https://github.com/rubocop-hq/rubocop/pull/6689): Support more complex argument patterns on `Rails/Validation` auto-correction. ([@r7kamura][])

## 0.63.1 (2019-01-22)

Expand Down
13 changes: 9 additions & 4 deletions lib/rubocop/cop/rails/validation.rb
Expand Up @@ -57,6 +57,9 @@ def on_send(node)
end

def autocorrect(node)
last_argument = node.arguments.last
return if !last_argument.literal? && !last_argument.splat_type?

lambda do |corrector|
corrector.replace(node.loc.selector, 'validates')
correct_validate_type(corrector, node)
Expand All @@ -75,12 +78,14 @@ def preferred_method(method)
end

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

if options
corrector.replace(options.loc.expression,
"#{validate_type}: #{braced_options(options)}")
if last_argument.hash_type?
corrector.replace(
last_argument.loc.expression,
"#{validate_type}: #{braced_options(last_argument)}"
)
else
corrector.insert_after(node.loc.expression,
", #{validate_type}: true")
Expand Down
152 changes: 124 additions & 28 deletions spec/rubocop/cop/rails/validation_spec.rb
Expand Up @@ -20,34 +20,130 @@
end
end

describe 'autocorrect' do
described_class::TYPES.each do |parameter|
it "corrects validates_#{parameter}_of" do
new_source = autocorrect_source(
"validates_#{parameter}_of :full_name, :birth_date"
)
expect(new_source).to eq(
"validates :full_name, :birth_date, #{parameter}: true"
)
end
end

it 'corrects validates_numericality_of with options' do
new_source = autocorrect_source(
'validates_numericality_of :age, minimum: 0, maximum: 122'
)
expect(new_source).to eq(
'validates :age, numericality: { minimum: 0, maximum: 122 }'
)
end

it 'autocorrect validates_numericality_of with options in braces' do
new_source = autocorrect_source(
'validates_numericality_of :age, { minimum: 0, maximum: 122 }'
)
expect(new_source).to eq(
'validates :age, numericality: { minimum: 0, maximum: 122 }'
)
describe '#autocorrect' do
shared_examples 'auto-corrects' do
it 'auto-corrects' do
expect(autocorrect_source(source)).to eq(auto_corrected_source)
end
end

shared_examples 'does not auto-correct' do
it 'does not auto-correct' do
expect(autocorrect_source(source)).to eq(source)
end
end

described_class::TYPES.each do |type|
context "with validates_#{type}_of" do
let(:auto_corrected_source) do
"validates :full_name, :birth_date, #{type}: true"
end

let(:source) do
"validates_#{type}_of :full_name, :birth_date"
end

include_examples 'auto-corrects'
end
end

context 'with single attribute name' do
let(:auto_corrected_source) do
'validates :a, numericality: true'
end

let(:source) do
'validates_numericality_of :a'
end

include_examples 'auto-corrects'
end

context 'with multi attribute names' do
let(:auto_corrected_source) do
'validates :a, :b, numericality: true'
end

let(:source) do
'validates_numericality_of :a, :b'
end

include_examples 'auto-corrects'
end

context 'with non-braced hash literal' do
let(:auto_corrected_source) do
'validates :a, :b, numericality: { minimum: 1 }'
end

let(:source) do
'validates_numericality_of :a, :b, minimum: 1'
end

include_examples 'auto-corrects'
end

context 'with braced hash literal' do
let(:auto_corrected_source) do
'validates :a, :b, numericality: { minimum: 1 }'
end

let(:source) do
'validates_numericality_of :a, :b, { minimum: 1 }'
end

include_examples 'auto-corrects'
end

context 'with splat' do
let(:auto_corrected_source) do
'validates :a, *b, numericality: true'
end

let(:source) do
'validates_numericality_of :a, *b'
end

include_examples 'auto-corrects'
end

context 'with splat and options' do
let(:auto_corrected_source) do
'validates :a, *b, :c, numericality: { minimum: 1 }'
end

let(:source) do
'validates_numericality_of :a, *b, :c, minimum: 1'
end

include_examples 'auto-corrects'
end

context 'with trailing send node' do
let(:source) do
'validates_numericality_of :a, b'
end

include_examples 'does not auto-correct'
end

context 'with trailing constant' do
let(:source) do
'validates_numericality_of :a, B'
end

include_examples 'does not auto-correct'
end

context 'with trailing local variable' do
let(:source) do
<<-RUBY.strip_indent
b = { minimum: 1 }
validates_numericality_of :a, b
RUBY
end

include_examples 'does not auto-correct'
end
end
end