Misha Krul
Misha Krul

Reputation: 397

Rails ActionView::MissingTemplate, Template Is Missing for mailer

I have a mailer class called ContactUsMailer that inherits from ActionMailer::Base.

class ContactUsMailer < ActionMailer::Base
  default from: '[email protected]'

  def contact_us(name:, email:, message:)
    @name = name
    @email = email
    @message = message
    mail(
      to: '[email protected]',
      subject: "New email inquiry from #{@name} (#{@email})",
      template_path: 'views/mailers/contact_us_mailer',
      template_name: 'contact_us'
    )
  end
end

It is being called from the ContactUsController.

class ContactUsController < ApplicationController

  def index
  end

  def create
    if params[:name].blank? || params[:email].blank? || params[:message].blank?
      flash[:error] = "Your name, email, and a message are required. Please try again."
    else
      ContactUsMailer.contact_us(
        name: params[:name],
        email: params[:email],
        message: params[:message]
      ).deliver!

      flash[:notice] = "Thank you for contacting us. We will get back to you shortly."
    end

    redirect_to contact_us_path
  end

  private

end

My mailer templates exist under views/mailers/contact_us_mailer.

<!DOCTYPE html>
<html>
  <head>
    <meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
  </head>
  <body>
    <p>
      New inquiry from <%= @name %>
    </p>
    <p>
      Email: <%= @email %>
    </p>
    ---------
    Message: <%= @message %>
  </body>
</html>

If I do not add body: to the mail() call in ContactUsMailer, I receive the following error:


Template is missing
Missing template views/mailers/contact_us_mailer/contact_us with "mailer". Searched in: * "views/mailers/contact_us_mailer" 

If I DO add body: @message to the mail() call, I receive no errors and the email sends successfully, however the email contains only the message and not the template itself.

I do not understand why Rails is failing to recognize the template, even when I specify a path. Digging into the collect_responses_from_templates(headers) method, it clearly recognizes the template data in the headers.

def collect_responses_from_templates(headers)
=> 986:         templates_path = headers[:template_path] || self.class.mailer_name
   987:         templates_name = headers[:template_name] || action_name
   988: 
   989:         each_template(Array(templates_path), templates_name).map do |template|
   990:           format = template.format || self.formats.first
(byebug) headers[:template_path]
"views/mailers/contact_us_mailer"

Any advice for how to proceed would be greatly appreciated.

Upvotes: 0

Views: 70

Answers (1)

Misha Krul
Misha Krul

Reputation: 397

Figured it out.

I tried regenerating the mailer via bundle exec rails generate mailer contact_us and noticed that it created a mailer at app/mailers/contact_us_mailer.rb .. My original mailer was located at app/mailers/contact_us_mailer/. Something about having the namespaced path must have been throwing off the Rails magic.

Upvotes: 1

Related Questions