Search code examples
ruby-on-railsdevisedevise-invitable

Can't get users to create a custom message with devise invitable


I have 2 user-like models in my app: 'Participant' and 'Member'. I'm trying to allow them to include a custom message when they invite other members/participants through Devise Invitable. However, I can't make it work.

I'm following this official tutorial so I've made the following changes to override Devise Invitable Controller but when using pry it seems that this custom controller goes untouched when sending an invite. What am I doing wrong:

controllers/participants/invitations_controller.rb

class Participants::InvitationsController < Devise::InvitationsController
      before_action :update_sanitized_params, only: :update

  def create
    binding.pry
    @from    = params[:from]
    @subject = params[:invite_subject]
    @content = params[:invite_content]

    @participant = Participant.invite!(params[:user], current_member) do |u| #XXX Check if :user should be changed
      u.skip_invitation = true
    end

    ParticipantInvitationNotificationMailer.invite_message(@participant, @from, @subject, @content).deliver if @participant.errors.empty?
    @participant.invitation_sent_at = Time.now.utc # mark invitation as delivered

    if @participant.errors.empty?
      flash[:notice] = "successfully sent invite to #{@participant.email}"
      respond_with @participant, :location => root_path
    else
      render :new
    end
  end

  def update
    respond_to do |format|
      format.js do
        invitation_token = Devise.token_generator.digest(resource_class, :invitation_token, update_resource_params[:invitation_token])
        self.resource = resource_class.where(invitation_token: invitation_token).first
        resource.skip_password = true
        resource.update_attributes update_resource_params.except(:invitation_token)
      end
      format.html do
        super
      end
    end
  end

  protected

  def update_sanitized_params
    devise_parameter_sanitizer.permit(:accept_invitation, keys: [:password, :password_confirmation, :invitation_token, :username])
  end


end

config/routes.rb

Rails.application.routes.draw do
  devise_for :members, controllers: { invitations: "members/invitations" }
  devise_for :participants, controllers: { invitations: "participants/invitations" }
end

models/participant.rb

class Participant < ApplicationRecord
  attr_reader :raw_invitation_token
end

mailers/notification_mailer.rb

class NotificationMailer < ApplicationMailer
  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.last_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

If I send an invitation:with Participant.invite!({:email => '[email protected]'}, Member.first) the invitation is sent through the default mailer as shown in the console but not through my new mailer. why?

  Rendering /Users/andres/.rvm/gems/ruby-2.4.0@pixiebob/gems/devise_invitable-1.7.1/app/views/devise/mailer/invitation_instructions.html.erb
  Rendered /Users/andres/.rvm/gems/ruby-2.4.0@pixiebob/gems/devise_invitable-1.7.1/app/views/devise/mailer/invitation_instructions.html.erb (0.6ms)
  Rendering /Users/andres/.rvm/gems/ruby-2.4.0@pixiebob/gems/devise_invitable-1.7.1/app/views/devise/mailer/invitation_instructions.text.erb
  Rendered /Users/andres/.rvm/gems/ruby-2.4.0@pixiebob/gems/devise_invitable-1.7.1/app/views/devise/mailer/invitation_instructions.text.erb (0.8ms)

Solution

  • Finally, I could solve this issue.

    It ended up being a rookie mistake I was thinking that calling the invite! method would have anything to do with the custom create method in the custom invitations controller.

    I had of course to reach the create method through the specified route and within that method prevent the invite! method to send the email through the default mailer using code below (as established clearly in the Devise Invitable Documentation):

      @participant = Participant.invite!({:email => @invitation_draft.email}, current_member) do |u|
        u.skip_invitation = true
      end  
    

    After this we can call any custom mailer in the create method.