Class: RuboCop::Cop::DevDoc::Rails::NoPerformLaterInModel

Inherits:
Base
  • Object
show all
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 ‘transaction` and `perform_later` (the job may run before the transaction commits and read stale data — see `DevDoc/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
    `transaction` block.
    

    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.

Examples:

# bad (in app/models/order.rb)
def finalize
  save!
  OrderJob.perform_later(self)
end

# good — explicit method communicates the side effect
def finalize_with_job
  save!
  OrderJob.perform_later(self)
end

Constant Summary collapse

MSG =
'Avoid `perform_later` in model files. Call it from the controller, ' \
'or use an explicit method name to signal the side effect.'.freeze
RESTRICT_ON_SEND =
%i[perform_later].freeze

Instance Method Summary collapse

Instance Method Details

#on_send(node) ⇒ Object



54
55
56
# File 'lib/rubocop/cop/dev_doc/rails/no_perform_later_in_model.rb', line 54

def on_send(node)
  add_offense(node.loc.selector)
end