Skip to content

Commit

Permalink
Preserve original callback execution order
Browse files Browse the repository at this point in the history
This cop registers an offense when a callback appears after another
callback that will be executed later in the record's lifecycle.

The auto-correct logic currently always moves the offending callback to
before the first callback in the class. This does eventually produce the
correct result, but it's not very efficient, and can reorder callbacks
of the same type, which changes the order in which they're executed.

By moving the offending callback above the preceding one, the sort
becomes stable and the original callback execution order is preserved.
  • Loading branch information
eugeneius committed Jul 30, 2020
1 parent ecf7b32 commit 9300bbe
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 5 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
* [#52](https://github.com/rubocop-hq/rubocop-rails/issues/52): Add new `Rails/AfterCommitOverride` cop. ([@fatkodima][])
* [#274](https://github.com/rubocop-hq/rubocop-rails/pull/274): Add new `Rails/WhereNot` cop. ([@fatkodima][])

### Bug fixes

* [#313](https://github.com/rubocop-hq/rubocop-rails/pull/313): Fix `Rails/ActiveRecordCallbacksOrder` to preserve the original callback execution order. ([@eugeneius][])

### Changes

* [#312](https://github.com/rubocop-hq/rubocop-rails/pull/312): Mark `Rails/MailerName` as unsafe for auto-correct. ([@eugeneius][])

## 2.7.1 (2020-07-26)

### Bug fixes
Expand All @@ -18,7 +26,6 @@
### Changes

* [#301](https://github.com/rubocop-hq/rubocop-rails/issues/301): Set disalbed by default for `Rails/PluckId`. ([@koic][])
* [#312](https://github.com/rubocop-hq/rubocop-rails/pull/312): Mark `Rails/MailerName` as unsafe for auto-correct. ([@eugeneius][])

## 2.7.0 (2020-07-21)

Expand Down
6 changes: 2 additions & 4 deletions lib/rubocop/cop/rails/active_record_callbacks_order.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ class ActiveRecordCallbacksOrder < Cop
after_touch
].freeze

CALLBACKS_ORDER_MAP = Hash[
CALLBACKS_IN_ORDER.map.with_index { |name, index| [name, index] }
].freeze
CALLBACKS_ORDER_MAP = CALLBACKS_IN_ORDER.each_with_index.to_h.freeze

def on_class(class_node)
previous_index = -1
Expand All @@ -68,7 +66,7 @@ def on_class(class_node)

# Autocorrect by swapping between two nodes autocorrecting them
def autocorrect(node)
previous = left_siblings_of(node).find do |sibling|
previous = left_siblings_of(node).reverse_each.find do |sibling|
callback?(sibling)
end

Expand Down
19 changes: 19 additions & 0 deletions spec/rubocop/cop/rails/active_record_callbacks_order_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,25 @@ class User < ApplicationRecord
RUBY
end

it 'preserves the original order of callbacks of the same type' do
expect_offense(<<~RUBY)
class User < ApplicationRecord
after_commit :after_commit_callback
after_save :after_save_callback1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `after_save` is supposed to appear before `after_commit`.
after_save :after_save_callback2
end
RUBY

expect_correction(<<~RUBY)
class User < ApplicationRecord
after_save :after_save_callback1
after_save :after_save_callback2
after_commit :after_commit_callback
end
RUBY
end

it 'does not register an offense when declared callbacks are correctly ordered' do
expect_no_offenses(<<~RUBY)
class User < ApplicationRecord
Expand Down

0 comments on commit 9300bbe

Please sign in to comment.