14

I am wondering on how do you access ActiveJob perform parameters in the resue block, such as

def perform object
end

rescue_from Exception do |e|
   if e.class != ActiveRecord::RecordNotFound
      **job.arguments.first** 
      # do something
   end
end

Thank You !!

ConfusedUser
  • 351
  • 1
  • 4
  • 14
  • Where is the exception occurring? In the perform method? If so, simply place your rescue block below the culprit code within the perform method. You'll have access to the `object` parameter as a local variable. – Noz Mar 16 '15 at 20:02
  • Noz, I have before_enqueue and around_perform as well hence the rescue_from. – ConfusedUser Mar 16 '15 at 20:04
  • I have not used either of those before, but can you not place your rescue block in either of those blocks? I don't think you want to be using `rescue_from` in your ActiveJob, a simple `rescue ActoveRecord::RecordNotFound => e` should suffice. – Noz Mar 16 '15 at 20:10
  • It is definitely supported (and helpful) to use `rescue_from` in ActiveJobs: http://edgeguides.rubyonrails.org/active_job_basics.html#exceptions Specifically, it is very useful in a Job base class (where similar failures can be consolidated to one `rescue_from` rather than copied into a dozen `perform` blocks). – Joe Atzberger Feb 09 '18 at 20:47

3 Answers3

19

It is possible with arguments inside the rescue_from block:

rescue_from(StandardError) do |exception|
  user = arguments[0]
  post = arguments[1]
  # ...      
end

def perform(user, post)
  # ...
end

This also works for callbacks as well (e.g. inside after_perform).

agorf
  • 191
  • 2
  • 5
  • 4
    Thanks, this worked for me (Rails 5.0.1, sidekiq 4.2.9). In the `rescue_from` block, `arguments[0]` gave me the first argument that was passed to `perform`. – DelPiero Apr 13 '17 at 13:35
2

I had no idea on that as well, then simply decided to try and use self inside the rescue_from block, and it worked.

rescue_from(StandardError) do |ex|
  puts ex.inspect
  puts self.job_id
  # etc.
end

As a side note -- NEVER ever rescue Exception:

Why is it a bad style to `rescue Exception => e` in Ruby?

Community
  • 1
  • 1
dimitarvp
  • 2,316
  • 2
  • 20
  • 29
  • rescue_from() only works with exceptions from StandardError down: https://github.com/rails/rails/issues/28874#issuecomment-297599254 – SteveRawlinson Jan 26 '21 at 14:17
1

You can access all Bindings by ex.bindings. To make sure you get the correct binding for your job you should check the receiver like this1:

method_binding = ex.bindings.find { |b| b.receiver.is_a?(self.class) }

Then you can get all local variables with .local_variable_get. Since method arguments are also local variables, you can at least explicitly fetch them:

user = method_binding.local_variable_get(:user)
post = method_binding.local_variable_get(:post)

So for you example:

def perform object
end

rescue_from Exception do |e|
   if e.class != ActiveRecord::RecordNotFound
      method_binding = ex.bindings.find { |b| b.receiver.is_a?(self.class) }
      object = method_binding.local_variable_get(:object)
      # do something
   end
end

1. It is still possible that this binding is not the one of perform if you call other instance methods in your job's perform method and the error happens there. This can also be taken in account but is left out for brevity.

Markus
  • 5,667
  • 4
  • 48
  • 64