Class: RuboCop::Cop::DevDoc::Rails::NoDeliverLaterInTransaction
- Inherits:
-
Base
- Object
- Base
- RuboCop::Cop::DevDoc::Rails::NoDeliverLaterInTransaction
- Defined in:
- lib/rubocop/cop/dev_doc/rails/no_deliver_later_in_transaction.rb
Overview
Avoid ‘deliver_later` and `perform_later` inside a `transaction` block.
## Rationale Do not use ‘perform_later` or `deliver_later` inside a transaction block because there is a possibility that the job will use stale data, as the transaction has not yet completed (not yet committed changes to the database).
❌
organization.transaction do
if organization.save
# This mailer may receive the organization with stale data
# (data before `save()`)
OrganizationMailer.with(organization: organization).deliver_later
end
end
✔️
organization.transaction do
save_succeeded = organization.save
end
if save_succeeded
OrganizationMailer.with(organization: organization).deliver_later
end
## Watch out for indirect calls Some libraries call ‘perform_later` / `deliver_later` behind the scenes — e.g. `@user.send_verification_email!` from the Devise gem. This cop cannot detect those wrappers; reviewers should still flag them when they appear inside a `transaction` block.
Constant Summary collapse
- MSG =
'`%<method>s` inside a `transaction` block may use stale data. Move it outside the transaction.'.freeze
- RESTRICT_ON_SEND =
%i[deliver_later perform_later].freeze
Instance Method Summary collapse
Instance Method Details
#on_send(node) ⇒ Object
52 53 54 55 56 |
# File 'lib/rubocop/cop/dev_doc/rails/no_deliver_later_in_transaction.rb', line 52 def on_send(node) return unless inside_transaction?(node) add_offense(node.loc.selector, message: format(MSG, method: node.method_name)) end |