Class: RuboCop::Cop::Rails::SaveBang
- Inherits:
-
Base
- Object
- Base
- RuboCop::Cop::Rails::SaveBang
- Extended by:
- AutoCorrector
- Includes:
- NegativeConditional
- Defined in:
- lib/rubocop/cop/rails/save_bang.rb
Overview
Identifies possible cases where Active Record save! or related should be used instead of save because the model might have failed to save and an exception is better than unhandled failure.
This will allow:
-
update or save calls, assigned to a variable, or used as a condition in an if/unless/case statement.
-
create calls, assigned to a variable that then has a call to ‘persisted?`, or whose return value is checked by `persisted?` immediately
-
calls if the result is explicitly returned from methods and blocks, or provided as arguments.
-
calls whose signature doesn’t look like an ActiveRecord persistence method.
By default it will also allow implicit returns from methods and blocks. that behavior can be turned off with ‘AllowImplicitReturn: false`.
You can permit receivers that are giving false positives with ‘AllowedReceivers: []`
Constant Summary collapse
- MSG =
'Use `%<prefer>s` instead of `%<current>s` if the return value is not checked.'
- CREATE_MSG =
"#{MSG} Or check `persisted?` on model returned from `%<current>s`."
- CREATE_CONDITIONAL_MSG =
'`%<current>s` returns a model which is always truthy.'
- CREATE_PERSIST_METHODS =
%i[create create_or_find_by first_or_create find_or_create_by].freeze
- MODIFY_PERSIST_METHODS =
%i[save update update_attributes destroy].freeze
- RESTRICT_ON_SEND =
(CREATE_PERSIST_METHODS + MODIFY_PERSIST_METHODS).freeze
Class Method Summary collapse
Instance Method Summary collapse
- #after_leaving_scope(scope, _variable_table) ⇒ Object
- #check_assignment(assignment) ⇒ Object
-
#on_send(node) ⇒ Object
(also: #on_csend)
rubocop:disable Metrics/CyclomaticComplexity.
Class Method Details
.joining_forces ⇒ Object
132 133 134 |
# File 'lib/rubocop/cop/rails/save_bang.rb', line 132 def self.joining_forces VariableForce end |
Instance Method Details
#after_leaving_scope(scope, _variable_table) ⇒ Object
136 137 138 139 140 141 142 |
# File 'lib/rubocop/cop/rails/save_bang.rb', line 136 def after_leaving_scope(scope, _variable_table) scope.variables.each_value do |variable| variable.assignments.each do |assignment| check_assignment(assignment) end end end |
#check_assignment(assignment) ⇒ Object
144 145 146 147 148 149 150 151 152 |
# File 'lib/rubocop/cop/rails/save_bang.rb', line 144 def check_assignment(assignment) node = right_assignment_node(assignment) return unless node&.send_type? return unless persist_method?(node, CREATE_PERSIST_METHODS) return if persisted_referenced?(assignment) register_offense(node, CREATE_MSG) end |
#on_send(node) ⇒ Object Also known as: on_csend
rubocop:disable Metrics/CyclomaticComplexity
155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/rubocop/cop/rails/save_bang.rb', line 155 def on_send(node) return unless persist_method?(node) return if return_value_assigned?(node) return if implicit_return?(node) return if check_used_in_condition_or_compound_boolean(node) return if argument?(node) return if explicit_return?(node) return if checked_immediately?(node) register_offense(node, MSG) end |