Search code examples
ruby-on-railsactionmailerdevelopment-environment

Delivery method based on condition? Rails


Rails 4.1.4, I have many classes of Mailers, and they all have different delivery methods. Now this has caused me a problem.

In development and test environment when I have delivery_method as :test then if I perform and delivery using the below class then the delivery method becomes :custom_method, even though I have mentioned config.delivery_method = :test in the rails environment files.

class CustomMailer < ActionMailer::Base

  default :delivery_method => :custom_method,
          from: "...",
          reply_to: '...'

  def emailer(emails)
    mail(to: emails, subject: 'test')
  end

end

What is the right way of changing the :custom_method to :test in development and test environments ?

One possible solution I have implemented which works is this:

class CustomMailer < ActionMailer::Base

  DELIVERY_METHOD = Rails.env == 'production' ? :custom_method : :test

  default :delivery_method => DELIVERY_METHOD,
          from: "...",
          reply_to: '...'

  def emailer(emails)
    mail(to: emails, subject: 'test')
  end

end

This works for me but I feel this is not a good way because I have to write this line:

DELIVERY_METHOD = Rails.env == 'production' ? :custom_method : :test

in every Mailer class and that can cause redundancy. Would be great if it could be handled in some common way.

Please note that there are different delivery methods for every Mailer class.


Solution

  • The approach you're taking certainly works, but I believe that querying Rails.env in your code is an anti-pattern.

    You could instead use the application configuration by setting a custom config attribute. Here's an example:

    # config/production.rb
    Rails.application.configure do
      # by having this configured by an environment variable 
      # you can have different values in staging, 
      # develop, demo, etc.. They all use "production" env.
      config.x.mailer_livemode = ENV['MAILER_LIVEMODE']
    end
    
    # config/development.rb
    Rails.application.configure do
      config.x.mailer_livemode = false
    end
    
    # config/test.rb
    Rails.application.configure do
      config.x.mailer_livemode = false
    end
    
    # app/mailers/custom_mailer.rb
    default delivery_method: Rails.application.config.x.mailer_livemode ? :custom_method : :test
    

    The flexibility is superior. You can have more that one configuration variables working together, set the delivery_method straight in config, etc.

    Most importantly, you don't rely on something irrelevant (the Rails.env) for something that concerns how your emails are sent.