-
Notifications
You must be signed in to change notification settings - Fork 553
Customizing for different Invite use cases (emails etc.)
Sometimes you want to be able to send different invites for a variety of different reasons. Eg. Inviting a VIP user vs Inviting a regular user. Here is an example of doing it for a "friend" and for a "guest"
In your devise model, put:
attr_accessor :invitation_instructions
def self.invite_guest!(attributes={}, invited_by=nil)
self.invite!(attributes, invited_by) do |invitable|
invitable.invitation_instructions = :guest_invitation_instructions
end
end
def self.invite_friend!(attributes={}, invited_by=nil)
self.invite!(attributes, invited_by) do |invitable|
invitable.invitation_instructions = :friend_invitation_instructions
end
end
From here if you run User.invite_guest!(:email => '[email protected]')
you will get the exact same email.
The way to fix this is to create your own mailer class that inherits from Devise::Mailer, and modify invitation_instructions
method yourself. EG.
class InviteMailer < Devise::Mailer
def invitation_instructions(record, token, opts={})
@token = token
devise_mail(record, record.invitation_instructions || :invitation_instructions, opts)
end
end
To make InviteMailer
your default class to send emails (wont override your other emails, which will still be sent by devise mailer) add this line to config/initializers/devise.rb
:
config.mailer = "InviteMailer"
Lastly, create your views in views/invite_mailer/guest_invitation_instructions
and you should be all set!
NOTE: When you create custom mailer (for example "InviteMailer") old devise mailer views should be moved to new mailer directory (just copy files from /app/views/devise/mailer/ to /app/views/invite_mailer/).
Sometimes you might want to add a dynamic email header instead of pulling something statically from config/locals
. For example, a personalized custom subject header. Here's an easy way to achieve this in devise versions below 2.2.0.
class User < ActiveRecord::Base
#... regular implementation ...
# This method is called internally during the Devise invitation process. We are
# using it to allow for a custom email subject. These options get merged into the
# internal devise_invitable options. Tread Carefully.
#
def headers_for(action)
return {} unless invited_by && action == :invitation_instructions
{ subject: "#{invited_by.full_name} has given you access to their account" }
end
end
Sometimes you may want to allow users to customize the message being sent, e.g. add a personal greeting to the standard message.
To accomplish this you can use your own mailer instead of having devise email things for you.
class User < ActiveRecord::Base
attr_reader :raw_invitation_token
end
class InvitationsController < Devise::InvitationsController
def create
@from = params[:from]
@subject = params[:invite_subject]
@content = params[:invite_content]
@user = User.invite!(params[:user], current_user) do |u|
u.skip_invitation = true
end
NotificationMailer.invite_message(@user, @from, @subject, @content).deliver if @user.errors.empty?
if @user.errors.empty?
@user.update_column :invitation_sent_at, Time.now.utc # mark invitation as delivered
flash[:notice] = "successfully sent invite to #{@user.email}"
respond_with @user, :location => root_path
else
render :new
end
end
end
class NotificationMailer < ActionMailer::Base
def invite_message(user, from, subject, content)
@user = user
@token = user.raw_invitation_token
invitation_link = accept_user_invitation_url(:invitation_token => @token)
mail(:from => from, :bcc => from, :to => @user.email, :subject => subject) do |format|
content = content.gsub '{{first_name}}', user.first_name
content = content.gsub '{{last_name}}', user.first_name
content = content.gsub '{{full_name}}', user.full_name
content = content.gsub('{{invitation_link}}', invitation_link)
format.text do
render :text => content
end
end
end
end
The raw_invitation_token
only exists in newer versions of devise_invitable (compatible with devise >= 3.1).
Note that you must send the email with the user object instance that generated the token, as user.raw_invitation_token
is available only to the instance and is not persisted in the database.
We are essentially skipping the devise invitation email process all together and using our own mailer. We take the content as a parameter and send it as the body of the email. We even substitute placeholders with their actual values.
This solution will give you a lot of flexibility to do whatever you want with emails. You can even add a tracking pixel to it if you would like.