ruby-on-railsdeviseruby-on-rails-7devise-invitable

NoMethodError (undefined method `deliver_invitation') devise invitable rails


Hello I have an app where a user is invited as an attendee

In the attendee controller, when the attendee is created the user is created but not sent an invite to the system

attendees_controller.rb

def create
    @attendee = Attendee.new(attendee_params)
    @user = User.invite!({email: "#{@attendee.email}"}, current_user) do |u|
      u.skip_invitation = true
    end 
    @attendee.user_id = @user.id
    respond_to do |format|
      if @attendee.save
        format.html { redirect_to meeting_url(@attendee.meeting), notice: "Attendee was successfully created." }
        format.json { render :show, status: :created, location: @attendee }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @attendee.errors, status: :unprocessable_entity }
      end
    end
  end

in the same controller i then have a send_invite

 def send_invite
    @attendee = Attendee.find(params[:attendee_id])
    User.where(id: @attendee.user_id).deliver_invitation
    redirect_to meeting_url(@attendee.meeting)
  end

when i hit it via a button I get

NoMethodError in AttendeesController#send_invite undefined method `deliver_invitation' for #<ActiveRecord::Relation

[devise_invitable][1] clearly states

If you want to create the invitation but not send it, you can set skip_invitation to true.

user = User.invite!(email: 'new_user@example.com', name: 'John Doe') do |u|
  u.skip_invitation = true
end
# => the record will be created, but the invitation email will not be sent

When generating the accept_user_invitation_url yourself, you must use the raw_invitation_token. This value is temporarily available when you invite a user and will be decrypted when received.

accept_user_invitation_url(invitation_token: user.raw_invitation_token)

When skip_invitation is used, you must also then set the invitation_sent_at field when the user is sent their token. Failure to do so will yield “Invalid invitation token” error when the user attempts to accept the invite. You can set the column, or call deliver_invitation to send the invitation and set the column:

user.deliver_invitation

What am I missing? [1]: https://github.com/scambra/devise_invitable#send-an-invitation-


Solution

  • I guess .deliver_invitation is an instance method on the User Model. (through devise_invitable).
    In that case you would probably want something like this:

    User.where(id: @attendee.user_id).each do |user|
       user.deliver_invitation
    end