I am writing an invitation form with Vue.js. The invites should POST to a Rails 5 API. I am using devise_invitable
for the invitation logic and email dispatch. However, I am having a problem with intercepting the create
method, as I will be sending the invitation to multiple users so I want to perform a User.invite!
for each user in the params.
My invite.vue file, which contains the form to post:
<template>
<b-row>
<b-col>
Invite {{form.length}} members
<b-form @submit.prevent="submitStaffInvite" id='staffInvite'>
<div v-for="(row, idx) in form">
<b-row>
<b-col cols="3">
<b-form-group id="firstNameGroup" label="First name">
<b-form-input id="firstNameInput" name="user[first_name][]" type="text" v-model="row.firstName" autofocus></b-form-input>
</b-form-group>
</b-col>
<b-col cols="3">
<b-form-group id="lastNameGroup" label="Last name">
<b-form-input id="lastNameInput" name="user[last_name][]" type="text" v-model="row.lastName"></b-form-input>
</b-form-group>
</b-col>
<b-col cols="3">
<b-form-group id="emailGroup" label="Staff email">
<b-form-input id="emailInput" name="user[email][]" type="text" v-model="row.email"></b-form-input>
</b-form-group>
</b-col>
<b-col cols="3">
<b-button @click='removeRow(idx)'>Remove invitation</b-button>
</b-col>
</b-row>
</div>
<br />
<b-button-group>
<b-button @click.prevent='addRow'>Add invitation</b-button>
</b-button-group>
<br />
<b-button-group>
<b-button type="submit" variant="primary">Submit</b-button>
</b-button-group>
</b-form>
</b-col>
</b-row>
</template>
<script>
export default {
data: () => {
return {
form: [
{
email: '',
firstName: '',
lastName: ''
}
]
}
},
methods: {
addRow: function () {
this.form.push({
email: '',
firstName: '',
lastName: ''
})
},
removeRow: function (idx) {
this.form.splice(idx, 1)
},
submitStaffInvite: function () {
this.$axios.post('http://localhost:3001/auth/invitation', this.form)
.then((res) => {
if (res.status === 200) {
this.$notify({
text: res.data.message,
group: 'alerts',
type: 'success'
})
}
})
.catch(function (error) {
error.response.data.errors.forEach((err) => {
this.$notify({
text: err,
group: 'alerts',
type: 'warning'
})
})
})
}
}
}
</script>
my users/invitations_controller.rb
class Users::InvitationsController < Devise::InvitationsController
before_action :configure_permitted_parameters
def create
# TODO
# Send email to each user in the form.
end
def edit
sign_out send("current_#{resource_name}") if send("#{resource_name}_signed_in?")
set_minimum_password_length
resource.invitation_token = params[:invitation_token]
redirect_to "http://localhost:3001/auth/invitation/accept?invitation_token=#{params[:invitation_token]}"
end
def update
super do |resource|
if resource.errors.empty?
render json: { status: "Invitation Accepted!" }, status: 200
else
render json: resource.errors, status: 401
end
end
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:accept_invitation, keys: [:first_name, :last_name])
end
end
my routes.rb
Rails.application.routes.draw do
# Using devise_token_auth for the API
mount_devise_token_auth_for 'User', at: 'auth',
defaults: { format: :json },
controllers: {
invitations: 'users/invitations'
}
...
end
I can see that the following routes exist:
PUT /auth/invitation(.:format) devise/invitations#update
POST /auth/invitation(.:format) devise/invitations#create
The problem I can see here though is that I'd expect the routes to look like this:
PUT /auth/invitation(.:format) users/invitations#update
POST /auth/invitation(.:format) users/invitations#create
This behavior might be caused by the devise_token_auth
gem, which I'm not sure how to correct.
Again, when I submit this form I'd expect to be able to intercept the create
method, so to then call User.invite!
on all the users that are listed in the form. I've tried adding a byebug
or binding.pry
inside the create
method but the code doesn't appear to execute, which means it's being bypassed.
The error message I see is:
Processing by Devise::InvitationsController#create as HTML
Parameters: {"_json"=>[{"email"=>"asd@ad.com", "firstName"=>"Test", "lastName"=>"Last"}], "invitation"=>{"_json"=>[{"email"=>"asd@ad.com", "firstName"=>"Test", "lastName"=>"Last"}]}}
Completed 500 Internal Server Error in 0ms (ActiveRecord: 0.0ms)
ArgumentError (wrong number of arguments (given 1, expected 0)):
Am I not supposed to pass the form data to the devise_invitable
's create method? Any help is much appreciated.
Thanks in advance!
Try changing your routes to
mount_devise_token_auth_for 'User', at: 'auth', skip: [:invitations]
devise_for :users, path: "auth", only: [:invitations],
controllers: { invitations: 'users/invitations' }
For more information you can refer to this article