Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changed Devise mailer template path, now Devise Invitable's e-mail subject lines fail

I created a custom devise mailer to change the location of the Devise e-mail templates in views. I made the following changes:

#/config/initializers/devise
config.mailer = 'CustomDeviseMailer'

and

# app/mailers/customer_devise_mailer.rb
    def headers_for(action, opts)
        headers = {
            :subject       => translate(devise_mapping, action),
            :from          => mailer_sender(devise_mapping),
            :to            => resource.email,
            :template_path => '/mailers/devise'
        }.merge(opts)
    end

Now the templates for my e-mails are located in: /app/views/mailers/devise/

The problem is when a Devise Invitable .invite! call is made, the subject line for the email states the error: "translation missing: en.#<Devise::Mapping:0x007fe8fb6f4578>".

I suspect I need to make an adjustment to /config/locales/devise_invitable.en.yml file. I have also overridden the Devise Invitable controller with /app/controllers/invitations_controller.rb.

What additions should I make to the devise_invitable.en.yml file? Thanks.

like image 718
Joseph Novak Avatar asked Jan 30 '14 02:01

Joseph Novak


1 Answers

The solution I implemented was to disable the default Devise Invitable mailer and instead use my own. The solution is similar to that found in the guide "Allowing users to create a custom invite message" on the Devise Invitable wiki.

I made the following changes.

Change the config to a custom mailer:

# config/initializers/devise
config.mailer = 'CustomDeviseMailer'

Specify the new Devise e-mail template path in your custom mailer (and move the Devise e-mail templates to this folder):

# app/mailers/customer_devise_mailer.rb
def headers_for(action, opts)
    super.merge!({template_path: '/mailers/devise'}) # this moves the Devise template path from /views/devise/mailer to /views/mailer/devise
end

Generate a mailer to handle the overridden Devise Invitable e-mail with the command rails generate mailer InvitableMailer.

Override the create action on the Devise Invitable controller. The code you need will be similar to the following. I have left out my respond_to block because it's customized for my application.

# controllers/invitations_controller.rb
class InvitationsController < Devise::InvitationsController

    # POST /resource/invitation
    def create
        @invited_user = User.invite!(invite_params, current_inviter) do |u|
            # Skip sending the default Devise Invitable e-mail
            u.skip_invitation = true
        end

        # Set the value for :invitation_sent_at because we skip calling the Devise Invitable method deliver_invitation which normally sets this value
        @invited_user.update_attribute :invitation_sent_at, Time.now.utc unless @invited_user.invitation_sent_at
        # Use our own mailer to send the invitation e-mail
        InvitableMailer.invite_email(@invited_user, current_user).deliver

        respond_to do |format|
            # your own logic here. See the default code in the Devise Invitable controller.
        end
    end
end

The Invitations Controller now calls our generated mailer instead of the Default mailer. Add a method on our mailer to send the e-mail.

# app/mailers/invitable_mailer.rb
class InvitableMailer < ActionMailer::Base
    default from: "[email protected]"

    def invite_email(invited_user, current_invitor)
        @invited_user = invited_user
    @current_invitor = current_invitor

        # NOTE: In newever versions of Devise the token variable is :raw_invitation_token instead of :invitation_token
        # I am using Devise 3.0.1
        @token = @invited_user.invitation_token
        @invitation_link = accept_user_invitation_url(:invitation_token => @token)

        mail(to: @invited_user.email,
            from: "[email protected]",
            subject: "Invitation to SERVICE",
            template_path: "/mailers/devise")
    end
end

The template for my custom invitation e-mail is app/views/mailers/devise/invite_email.html.erb. In that e-mail I link to the accept invitation URL complete with the invitation token with the following code <%= link_to 'Accept invitation', @invitation_link %>

Also, I added attr_accessible :invitation_sent_at to my User model so that I could update the :invitation_sent_at attribute from the Invitations Controller.

I hope this helps.

like image 111
Joseph Novak Avatar answered Oct 11 '22 07:10

Joseph Novak