Class: RuboCop::Cop::DevDoc::Rails::NoPerformLaterInModel
- Inherits:
-
Base
- Object
- Base
- RuboCop::Cop::DevDoc::Rails::NoPerformLaterInModel
- Defined in:
- lib/rubocop/cop/dev_doc/rails/no_perform_later_in_model.rb
Overview
Avoid perform_later calls inside model files.
Rationale
Avoid using ActiveJob inside Models, because:
-
It is prone to conflicts between
transactionandperform_later(the job may run before the transaction commits and read stale data — seeDevDoc/Rails/NoDeliverLaterInTransaction). -
Execution flow control should be done in the Controller, not in the Model.
-
If it really must be done in the Model, name the method explicitly so the side effect is obvious at the call site.
❌ (in app/models/order.rb) def finalize save! OrderJob.perform_later(self) end
✔️ Explicit method name signals the side effect; reviewers immediately see that this should not be called inside a
transactionblock. def save_with_email_sending save! OrderJob.perform_later(self) end
NOTE: This cop flags any perform_later in app/models/**/*.rb,
including the legitimate "explicitly named method" case above. The
cop is intentionally conservative — disable per-line with a rubocop
comment when you have deliberately followed the naming convention.
Constant Summary collapse
- MSG =
'Avoid `%<method>s` in model files — it enqueues an ActiveJob (mailer deliveries ' \ 'included), with the same transaction/stale-data hazard as `perform_later`. Call it ' \ 'from the controller, or use an explicit method name to signal the side effect.'.freeze
- RESTRICT_ON_SEND =
deliver_later is ActiveJob under the hood (MailDeliveryJob) and enqueue is the primitive perform_later wraps — omitting either would leave an everyday spelling of the same async enqueue.
%i[perform_later perform_all_later deliver_later deliver_later! enqueue].freeze
Instance Method Summary collapse
Instance Method Details
#on_send(node) ⇒ Object
58 59 60 |
# File 'lib/rubocop/cop/dev_doc/rails/no_perform_later_in_model.rb', line 58 def on_send(node) add_offense(node.loc.selector, message: format(MSG, method: node.method_name)) end |