I’m trying to access request.host (well, ideally host_with_port) from a Mailer in Rails. The actually call to request.host is in a Helper:
#/app/helpers/confirmations_helper
module ConfirmationsHelper
def email_confirm_url(token)
"http://#{request.host_with_port}/confirm/#{token}" # failure: undefined method
end
end
#/app/mailers/user_mailer
class UserMailer < ActionMailer::Base
default from: "email@domain.com"
add_template_helper(ConfirmationsHelper) #get access to helpers/confirmations_helper.rb
def email_confirmation(user)
@user = user
@url = "http://www.domain.com/"
mail(to: user.email, subject: "Email Confirmation")
end
end
#config/environments/development.rb
...
config.action_mailer.default_url_options = { :host => "localhost:3000" }
Error I’m getting is:
ActionView::Template::Error:
undefined method `host' for nil:NilClass
This is telling you that
requestisnil. This is because outside of the scope of your controller (ie. in a class extendingActionMailer::Base)requestdoesn’t exist.You need to pass the
requestobject or just the part you need (request.host_with_port) to the mailer like you do other data likeuserin youremail_confirmation.So you have a create method with something like this
Inside your
Usermodel you have asend_email_confirmationmethod like thisYour mailer’s
email_confirmationlooks likeMaking the request to the mailer from your model is not the best idea; you should keep a cleaner separation of concerns. This is part of your problem and why you are finding unwanted complexity when trying to pass something like
requestfrom your controller action into the mailer template.What I might suggest is creating a worker class. Here I explain how to setup classes in
lib/– the same concept can be applied to something like alib/your_app/workers/user.rb.You could have the following in this class
Your controller action could then simply be
Your mailer method can now look like
Finally, you can remove
send_email_confirmationfrom your model as well as theemail_confirm_urlmethod from your helper since they’re no longer used. Two things to notetokenis being defined and usedAs you can see, by introducing this ‘worker’ class, there is a clean separation of functionality without duplication.