Reputation: 1930
I'm building an around_action
for my customer_mailer
class so that I don't have to wrap begin and rescue
around every time I call deliver_now
class CustomerMailer < ApplicationMailer
around_action :rescue_error
def send_email(customer)
...
end
def invite_friend(customer, invitee_email)
...
end
private
def rescue_error
yield
rescue => e
msg = "Caught exception! #{e} | #{action_name}"
puts msg
raise
end
end
So in the rescue, I want to log the message with information such as which action was called, I managed to find the method action_name
to show which action was called, but I couldn't find a way to retrieve the parameters that were passed into the action, any ideas?
Thanks!
Upvotes: 7
Views: 1326
Reputation: 399
Just store the parameters with which the action has been called to an instance variable, say @params
. Then these parameters will be accessible in rescue_error
via @params
. As per your example:
class CustomerMailer < ApplicationMailer
around_action :rescue_error
def send_email(customer)
@params = { customer: customer }
...
end
def invite_friend(customer, invitee_email)
@params = { customer: customer, invitee_email: invitee_email }
...
end
private
def rescue_error
begin
yield
rescue => e
msg = "Caught exception! #{e} | #{action_name} | #{@params.inspect}"
puts msg
raise
end
end
end
You can make the assignment to @params
a bit cleaner by using hash parameters in your actions, e.g.
def invite_friend(options = {})
@params = params
...
end
Of course, this requires accessing the parameters via options
, such as options[:customer]
to access customer
, and options[:invitee_email]
to access invitee_email
.
Upvotes: 2
Reputation: 2934
Before I answer your question: would using Bugsnag or something similar work in your case? Alternatively would rescue_from Exception, with: :exception_handler
work for you? (it won't allow you to reraise the exception though)
I dug into Rails source code and it seems that parameters are not stored anywhere. They are just passed as a splat to an instance method defined in your mailer class. However, there is a way to store them (without monkey-patching).
Mailers inherit from AbstractController::Base
. Looking at the snippet below:
# Call the action. Override this in a subclass to modify the
# behavior around processing an action. This, and not #process,
# is the intended way to override action dispatching.
#
# Notice that the first argument is the method to be dispatched
# which is *not* necessarily the same as the action name.
def process_action(method_name, *args)
send_action(method_name, *args)
end
# Actually call the method associated with the action. Override
# this method if you wish to change how action methods are called,
# not to add additional behavior around it. For example, you would
# override #send_action if you want to inject arguments into the
# method.
alias send_action send
we can see that we can override #send_action
and make it store the arguments. Add the following to your ApplicationMailer
:
class ApplicationMailer < ActionMailer::Base
def send_action(method_name, *args)
@action_args = args
super
end
end
The arguments will be available as @action_args
in all your mailers.
Upvotes: 4
Reputation: 406
The action name have to be yielded , it depends on the way you use your rescue_error .
Define a variable in the block that will be yielded
or raise specifics errors (maybe your custom exception class ) this way you'll retrieve invormation via "e"
post an exemple use case of rescue_error.
Upvotes: 0