Skip to content

Invite a Resource (or User) that Has Already Signed Up without Invitation

Mike Taylor edited this page Jan 20, 2015 · 2 revisions

DeviseInvitable provides a mechanism for re-sending invitations to users who have already been invited.

In my case, I wanted to invite an existing User because the invitation associates a generic user with an "admin" user, who controls the "team" and manages payment info for all invited users.

If you'd like to send an invitation to a user that has already signed up, but has not been invited (in other words, they signed up on their own), then you'll need to customize DeviseInvitable's behavior.

You'll want to add that new logic to either your InvitationsController's #create action or to the protected method, invite_resource, by overriding one of the methods (as recommended in the README section on Configuring Controllers).

Below is an example implementation. I've decided to add the new logic in the invite_resource method instead of the #create action.

The new logic checks if a user already exists with the submitted email address (invite_params[:email]). It also prevents a user from sending an invitation to their own email address.

Notice that the devise_invitable's invite_resource method returns an instance of a resource class, or in this example, a User instance (@user). The invite! class method returns an instance of a resource class, but the invite! instance method returns a Mail::Message object. It's easy to overlook that difference in return type. Adding the new logic to the invite_resource method ensures that the create action behaves the same regardless of whether the resource is a new or existing User.

class Users::InvitationsController < Devise::InvitationsController

  protected

  # invite_resource is called when creating invitation
  # should return an instance of resource class

  # this is devise_invitable's implementation
  # def invite_resource(&block)
  #   resource_class.invite!(invite_params, current_inviter, &block)
  # end

  def invite_resource(&block)
    @user = User.find_by(email: invite_params[:email])
    # @user is an instance or nil
    if @user && @user.email != current_user.email
      # invite! instance method returns a Mail::Message instance
      @user.invite!(current_user)
      # return the user instance to match expected return type
      @user
    else
      # invite! class method returns invitable var, which is a User instance
      resource_class.invite!(invite_params, current_inviter, &block)
    end
  end
end