Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 4 ActionMailer around_action | access action information (action_name & parameters)

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!

like image 941
lusketeer Avatar asked Jun 06 '16 16:06

lusketeer


People also ask

What is ActionMailer?

1 Introduction. Action Mailer allows you to send emails from your application using a mailer model and views. So, in Rails, emails are used by creating mailers that inherit from ActionMailer::Base and live in app/mailers. Those mailers have associated views that appear alongside controller views in app/views.

How do I send an email to ROR?

Go to the config folder of your emails project and open environment. rb file and add the following line at the bottom of this file. It tells ActionMailer that you want to use the SMTP server. You can also set it to be :sendmail if you are using a Unix-based operating system such as Mac OS X or Linux.


1 Answers

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.

like image 131
Greg Navis Avatar answered Oct 11 '22 02:10

Greg Navis