Home > Software design >  Confusion between url_for and host definition for ActionMailer
Confusion between url_for and host definition for ActionMailer

Time:02-18

Rails mailer instances do not have any context about the request. However this is needed to service multiple hosts. I was hoping to invoke url_for for the mailer, but I am confused to both the placing of it AND how it should be constructed (the api documentation provides examples for controllers, not mailers).

The form submission has a hidden_field :host, value: @site.host which percolates to the request

  Parameters: {"authenticity_token"=>"[FILTERED]", "user"=>{"email"=>"[email protected]", "host"=>"localhost"}

environments/development.rb has config.action_mailer.default_url_options commented out.
initializer for devise has config.parent_mailer = 'DeviseMailer' The users/passwords_controller.rb has been edited

class Users::PasswordsController < Devise::PasswordsController
   def create
puts params[:host]
     super
   end

and mailers/devise_mailer.rb sets

class DeviseMailer < ActionMailer::Base
  layout 'mailer'
  before_action :set_mailers_url_host

  def set_mailers_url_host
puts 'host'
puts params
    ActionMailer::Base.default_url_options[:host] = params[:user][:host]
  end

I did not expect the mailer to know the parameter as it is designed to inherit from < ActionMailer::Base
However, the log is indicating that the password controller generated is not being invoked. the 'host' string is being put, then an empty line indicates the mailer know nothing of the params

Processing by Devise::PasswordsController#create as HTML
[...]
  ↳ app/controllers/application_controller.rb:284:in `get_departments'
  User Load (2.5ms)  SELECT "users"...
  User Load (1.2ms)  SELECT "users"...
  TRANSACTION (1.0ms)  BEGIN
  User Update (1.7ms)  UPDATE "users" SET "reset_password_token" = $1, "reset_password_sent_at" = $2 WHERE "users"."id" = $3  [["reset_password_token", "..."], ["reset_password_sent_at", "..."], ["id", 45]]
  TRANSACTION (6.1ms)  COMMIT
host

Devise::Mailer#reset_password_instructions: processed outbound mail in 0.6ms
Completed 500 Internal Server Error in 745ms (ActiveRecord: 81.6ms | Allocations: 203970)
NoMethodError (undefined method `[]' for nil:NilClass):

app/mailers/devise_mailer.rb:8:in `set_mailers_url_host'

The error is expected given params[:user][:host] is an unknown entity to the mailer. The bypassing of the passwords controller, not.

Also attempted: commenting out the devise_mailer before_action and adding to the application_controller.rb, where @site is set in before_action :set_site :

  def default_url_options
    { host: @site.host, locale: I18n.locale }
  end

While this is the most succinct way of dealing with the case, that fails with error ActionView::Template::Error (Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true)

Why are the checks (via puts) in the passwords controller not being invoked?
How should url_for thus establish the required string based on params[:user][:site]

CodePudding user response:

This is a way to solve your issue but I'm not quite satisfied with the beauty of this.

  • Related