class RuboCop::Cop::Rails::ActiveRecordCallbacksOrder
This cop checks that Active Record callbacks are declared in the order in which they will be executed.
@example
# bad class Person < ApplicationRecord after_commit :after_commit_callback before_validation :before_validation_callback end # good class Person < ApplicationRecord before_validation :before_validation_callback after_commit :after_commit_callback end
Constants
- CALLBACKS_IN_ORDER
- CALLBACKS_ORDER_MAP
- MSG
Public Instance Methods
on_class(class_node)
click to toggle source
# File lib/rubocop/cop/rails/active_record_callbacks_order.rb, line 51 def on_class(class_node) previous_index = -1 previous_callback = nil defined_callbacks(class_node).each do |node| callback = node.method_name index = CALLBACKS_ORDER_MAP[callback] if index < previous_index message = format(MSG, current: callback, previous: previous_callback) add_offense(node, message: message) do |corrector| autocorrect(corrector, node) end end previous_index = index previous_callback = callback end end
Private Instance Methods
autocorrect(corrector, node)
click to toggle source
Autocorrect by swapping between two nodes autocorrecting them
# File lib/rubocop/cop/rails/active_record_callbacks_order.rb, line 73 def autocorrect(corrector, node) previous = node.left_siblings.reverse_each.find do |sibling| callback?(sibling) end current_range = source_range_with_comment(node) previous_range = source_range_with_comment(previous) corrector.insert_before(previous_range, current_range.source) corrector.remove(current_range) end
begin_pos_with_comment(node)
click to toggle source
# File lib/rubocop/cop/rails/active_record_callbacks_order.rb, line 111 def begin_pos_with_comment(node) annotation_line = node.first_line - 1 first_comment = nil processed_source.comments_before_line(annotation_line) .reverse_each do |comment| if comment.location.line == annotation_line && !inline_comment?(comment) first_comment = comment annotation_line -= 1 end end start_line_position(first_comment || node) end
buffer()
click to toggle source
# File lib/rubocop/cop/rails/active_record_callbacks_order.rb, line 134 def buffer processed_source.buffer end
callback?(node)
click to toggle source
# File lib/rubocop/cop/rails/active_record_callbacks_order.rb, line 95 def callback?(node) node.send_type? && CALLBACKS_ORDER_MAP.key?(node.method_name) end
defined_callbacks(class_node)
click to toggle source
# File lib/rubocop/cop/rails/active_record_callbacks_order.rb, line 85 def defined_callbacks(class_node) class_def = class_node.body if class_def class_def.each_child_node.select { |c| callback?(c) } else [] end end
end_position_for(node)
click to toggle source
# File lib/rubocop/cop/rails/active_record_callbacks_order.rb, line 106 def end_position_for(node) end_line = buffer.line_for_position(node.loc.expression.end_pos) buffer.line_range(end_line).end_pos end
inline_comment?(comment)
click to toggle source
# File lib/rubocop/cop/rails/active_record_callbacks_order.rb, line 126 def inline_comment?(comment) !comment_line?(comment.loc.expression.source_line) end
source_range_with_comment(node)
click to toggle source
# File lib/rubocop/cop/rails/active_record_callbacks_order.rb, line 99 def source_range_with_comment(node) begin_pos = begin_pos_with_comment(node) end_pos = end_position_for(node) Parser::Source::Range.new(buffer, begin_pos, end_pos) end
start_line_position(node)
click to toggle source
# File lib/rubocop/cop/rails/active_record_callbacks_order.rb, line 130 def start_line_position(node) buffer.line_range(node.loc.line).begin_pos - 1 end