Reputation: 1389
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.
Upvotes: 5
Views: 2044
Reputation: 3298
How about create an ApplicationMailer and get all other mailers to inherit from ApplicationMailer? This is the approach in Rails5 now. Code below shows one possible way to define delivery method in children mailers and inherit the selection logic from ApplicationMailer.
class ApplicationMailer < ActionMailer::Base
SELECTOR = Hash.new { |h,k| h[k] = k }
DELIVERY_METHOD = Rails.env.production? ? :custom_method : :test ##selection logic, use: env, env variables ...
end
class UserMailer < ApplicationMailer
SELECTOR[:custom_method] = :sendmail ##class-specific delivery method
default delivery_method: SELECTOR[DELIVERY_METHOD]
##....
end
Upvotes: 0
Reputation: 1322
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.
Upvotes: 4