Skip to content

Commit

Permalink
[Fix rubocop#120] Fix save-in-conditional checking in Rails/SaveBang
Browse files Browse the repository at this point in the history
Fixes rubocop#120.

The Rails/SaveBang rule emitted incorrect errors about using the return
value of save-like calls in conditional nodes. It did not differentiate
between such calls in the body versus the condition, where only the
latter is necessarily a boolean expression.
  • Loading branch information
jas14 committed Sep 11, 2019
1 parent 2058629 commit c5bb3fb
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 12 deletions.
10 changes: 5 additions & 5 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2019-07-20 17:51:45 +0900 using RuboCop version 0.72.0.
# on 2019-08-28 11:48:06 -0400 using RuboCop version 0.74.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
Expand All @@ -14,16 +14,16 @@ InternalAffairs/NodeDestructuring:
- 'lib/rubocop/cop/rails/relative_date_constant.rb'
- 'lib/rubocop/cop/rails/time_zone.rb'

# Offense count: 9
# Offense count: 10
Metrics/AbcSize:
Max: 17

# Offense count: 4
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 164
Max: 168

# Offense count: 23
# Offense count: 24
# Configuration parameters: CountComments, ExcludedMethods.
Metrics/MethodLength:
Max: 14
Expand All @@ -34,7 +34,7 @@ Metrics/MethodLength:
RSpec/ContextWording:
Enabled: false

# Offense count: 261
# Offense count: 264
# Configuration parameters: Max.
RSpec/ExampleLength:
Enabled: false
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

* [#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][])
* [#116](https://github.com/rubocop-hq/rubocop-rails/issues/116): Fix an incorrect autocorrect for `Rails/Presence` when `else` branch of ternary operator is not nil. ([@koic][])
### Bug fixes
* [#120](https://github.com/rubocop-hq/rubocop-rails/issues/120): Fix save-as-conditional checking. ([@jas14][])

## 2.3.1 (2019-08-26)

Expand Down Expand Up @@ -85,3 +87,4 @@
[@prathamesh-sonpatki]: https://github.com/prathamesh-sonpatki
[@MaximeLaurenty]: https://github.com/MaximeLaurenty
[@eugeneius]: https://github.com/eugeneius
[@jas14]: https://github.com/jas14
19 changes: 12 additions & 7 deletions lib/rubocop/cop/rails/save_bang.rb
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ def array_parent(node)
end

def check_used_in_conditional(node)
return false unless conditional?(node)
return false unless in_boolean_expr?(node)

unless MODIFY_PERSIST_METHODS.include?(node.method_name)
add_offense_for_node(node, CREATE_CONDITIONAL_MSG)
Expand All @@ -221,15 +221,20 @@ def check_used_in_conditional(node)
true
end

def conditional?(node) # rubocop:disable Metrics/CyclomaticComplexity
def in_boolean_expr?(node)
node = node.block_node || node
parent = node.parent
return false unless parent

condition = node.parent
return false unless condition
predicate_node?(parent) || condition_of?(parent, node)
end

def predicate_node?(node)
node.or_type? || node.and_type? || single_negative?(node)
end

condition.if_type? || condition.case_type? ||
condition.or_type? || condition.and_type? ||
single_negative?(condition)
def condition_of?(parent, node)
(parent.if_type? || parent.case_type?) && node == parent.condition
end

def allowed_receiver?(node)
Expand Down
8 changes: 8 additions & 0 deletions spec/rubocop/cop/rails/save_bang_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,14 @@
end
end

it "when using #{method} in the body of a oneline if" do
inspect_source("object.#{method} if false")

expect(cop.messages)
.to eq(["Use `#{method}!` instead of `#{method}` " \
'if the return value is not checked.'])
end

it "when using #{method} with a bunch of hashes & arrays" do
inspect_source(<<~RUBY)
return [{ success: object.#{method} }, true]
Expand Down

0 comments on commit c5bb3fb

Please sign in to comment.