Skip to content

Commit 340a54e

Browse files
committed
[Fix #190] Fix Rails/SaveBang when return value is checked immediately
Fixes #190. Rails/SaveBang had a false positive when the return value of a `create` call was checked directly with a call to `persisted?`.
1 parent fa74f7c commit 340a54e

File tree

5 files changed

+25
-9
lines changed

5 files changed

+25
-9
lines changed

.rubocop_todo.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This configuration was generated by
22
# `rubocop --auto-gen-config`
3-
# on 2019-09-13 11:45:19 -0400 using RuboCop version 0.74.0.
3+
# on 2020-01-22 14:25:37 -0500 using RuboCop version 0.79.0.
44
# The point is for the user to remove these configuration records
55
# one by one as the offenses are removed from the code base.
66
# Note that changes in the inspected code, or installation of new
@@ -14,27 +14,27 @@ InternalAffairs/NodeDestructuring:
1414
- 'lib/rubocop/cop/rails/relative_date_constant.rb'
1515
- 'lib/rubocop/cop/rails/time_zone.rb'
1616

17-
# Offense count: 11
17+
# Offense count: 10
1818
Metrics/AbcSize:
1919
Max: 17
2020

2121
# Offense count: 4
2222
# Configuration parameters: CountComments.
2323
Metrics/ClassLength:
24-
Max: 169
24+
Max: 173
2525

26-
# Offense count: 25
26+
# Offense count: 26
2727
# Configuration parameters: CountComments, ExcludedMethods.
2828
Metrics/MethodLength:
2929
Max: 14
3030

31-
# Offense count: 73
31+
# Offense count: 77
3232
# Configuration parameters: Prefixes.
3333
# Prefixes: when, with, without
3434
RSpec/ContextWording:
3535
Enabled: false
3636

37-
# Offense count: 277
37+
# Offense count: 287
3838
# Configuration parameters: Max.
3939
RSpec/ExampleLength:
4040
Enabled: false

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* [#184](https://github.com/rubocop-hq/rubocop-rails/issues/184): Fix `Rake/Environment` to allow task with no block. ([@hanachin][])
88
* [#122](https://github.com/rubocop-hq/rubocop-rails/issues/122): Fix `Exclude` paths that were not inherited. ([@koic][])
99
* [#187](https://github.com/rubocop-hq/rubocop-rails/pull/187): Fix an issue that excluded files in rubocop-rails did not work. ([@sinsoku][])
10+
* [#190](https://github.com/rubocop-hq/rubocop-rails/issues/190): Fix `Rails/SaveBang` when return value is checked immediately. ([@jas14][])
1011

1112
## 2.4.1 (2019-12-25)
1213

lib/rubocop/cop/rails/save_bang.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ module Rails
1212
# - update or save calls, assigned to a variable,
1313
# or used as a condition in an if/unless/case statement.
1414
# - create calls, assigned to a variable that then has a
15-
# call to `persisted?`.
15+
# call to `persisted?`, or whose return value is checked by
16+
# `persisted?` immediately
1617
# - calls if the result is explicitly returned from methods and blocks,
1718
# or provided as arguments.
1819
# - calls whose signature doesn't look like an ActiveRecord
@@ -137,16 +138,19 @@ def check_assignment(assignment)
137138
add_offense_for_node(node, CREATE_MSG)
138139
end
139140

140-
def on_send(node) # rubocop:disable Metrics/CyclomaticComplexity
141+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
142+
def on_send(node)
141143
return unless persist_method?(node)
142144
return if return_value_assigned?(node)
143145
return if implicit_return?(node)
144146
return if check_used_in_condition_or_compound_boolean(node)
145147
return if argument?(node)
146148
return if explicit_return?(node)
149+
return if checked_immediately?(node)
147150

148151
add_offense_for_node(node)
149152
end
153+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
150154
alias on_csend on_send
151155

152156
def autocorrect(node)
@@ -238,6 +242,10 @@ def conditional?(parent)
238242
parent.if_type? || parent.case_type?
239243
end
240244

245+
def checked_immediately?(node)
246+
node.parent && call_to_persisted?(node.parent)
247+
end
248+
241249
def allowed_receiver?(node)
242250
return false unless node.receiver
243251
return false unless cop_config['AllowedReceivers']

manual/cops_rails.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2193,7 +2193,8 @@ This will allow:
21932193
- update or save calls, assigned to a variable,
21942194
or used as a condition in an if/unless/case statement.
21952195
- create calls, assigned to a variable that then has a
2196-
call to `persisted?`.
2196+
call to `persisted?`, or whose return value is checked by
2197+
`persisted?` immediately
21972198
- calls if the result is explicitly returned from methods and blocks,
21982199
or provided as arguments.
21992200
- calls whose signature doesn't look like an ActiveRecord

spec/rubocop/cop/rails/save_bang_spec.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,12 @@ def whatever
571571
RUBY
572572
end
573573

574+
it "when using persisted? directly on #{method} return value" do
575+
expect_no_offenses(<<~RUBY)
576+
return unless object.#{method}.persisted?
577+
RUBY
578+
end
579+
574580
it "when using #{method} with `||`" do
575581
expect_no_offenses(<<~RUBY)
576582
def find_or_create(**opts)

0 commit comments

Comments
 (0)