Class: RuboCop::Cop::Rails::ActiveRecordCallbacksOrder

Inherits:
RuboCop::Cop
  • Object
show all
Defined in:
lib/rubocop/cop/rails/active_record_callbacks_order.rb

Overview

This cop checks that Active Record callbacks are declared in the order in which they will be executed.

Examples:

# 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

Constant Summary collapse

MSG =
'`%<current>s` is supposed to appear before `%<previous>s`.'
CALLBACKS_IN_ORDER =
i[
  after_initialize
  before_validation
  after_validation
  before_save
  around_save
  before_create
  around_create
  after_create
  before_update
  around_update
  after_update
  before_destroy
  around_destroy
  after_destroy
  after_save
  after_commit
  after_rollback
  after_find
  after_touch
].freeze
CALLBACKS_ORDER_MAP =
Hash[
  CALLBACKS_IN_ORDER.map.with_index { |name, index| [name, index] }
].freeze

Instance Method Summary collapse

Instance Method Details

#autocorrect(node) ⇒ Object

Autocorrect by swapping between two nodes autocorrecting them



70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/rubocop/cop/rails/active_record_callbacks_order.rb', line 70

def autocorrect(node)
  previous = left_siblings_of(node).find do |sibling|
    callback?(sibling)
  end

  current_range = source_range_with_comment(node)
  previous_range = source_range_with_comment(previous)

  lambda do |corrector|
    corrector.insert_before(previous_range, current_range.source)
    corrector.remove(current_range)
  end
end

#on_class(class_node) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# 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)
    end
    previous_index = index
    previous_callback = callback
  end
end