-
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_writer :invitation_instructions
def deliver_invitation
if @invitation_instructions
::Devise.mailer.send(@invitation_instructions, self).deliver
else
super
end
end
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 should get an error that says that Devise::Mailer has no method such as guest_invitation_instructions.
The way to fix this is to create your own mailer class that inherits from Devise::Mailer, and create those methods yourself. EG.
class InviteMailer < Devise::Mailer
def guest_invitation_instructions(record, opts={})
devise_mail(record, :guest_invitation_instructions, opts)
end
def friend_invitation_instructions(record, opts={})
devise_mail(record, :friend_invitation_instructions, opts)
end
end
in your devise.rb add the line
config.mailer = "InviteMailer"
to make invite mailer your default class to send emails (wont override your other emails, which will still be sent by devise mailer)
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 older than 2.2.0, for >= 2.2.0 you must overwrite mailer and customize it:
class User < ActiveRecord::Base
#... regular implementation ...
# This method is called interally 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
@user.invitation_sent_at = Time.now.utc # mark invitation as delivered
if @user.errors.empty?
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).
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.