Reputation: 119
I am currently using devise_invitable to submit an email that invites a new user. Each email you send out creates unique token which gets connects the two users if they accept the invitation. What I would like to do is for each current_user to have a unique invitation token that stays the same so they can tweet it, email it, etc. and anyone that accepts the invite by clicking on the link (www.mydomain.com/signup/'unique_current_user_token') will be taken to the signup form which will store the token in their 'account' so I can see who invited them. Does it make
Upvotes: 2
Views: 1154
Reputation: 783
I'll add a more detailed steps, just if someone struggles like me to implement the solution from @khaled_gomaa, that worked fine.
1a. If you are overriding devise registration controller, add it to this controller:
before_filter :configure_permitted_parameters
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :invited_by
end
1b. If you are not using a custom controller, add the following to the application constroller:
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :username
end
2. Run it in your console:
rails generate migration AddInvitationTokenToUsers invitation_token:string invited_by:integer
I'm not sure if it was in the original instructions but I think its really useful to set who invited a user.
Edit user model and add the following lines:
before_create :generate_invitation_token
def generate_invitation_token
self.invitation_token = Digest::SHA1.hexdigest([Time.now, rand].join)
end
3. I did not set the extra route in config/routes.rb
4. That's the part that was more confusing for me. Not sure if I'm not fully following the original instructions, but it worked fine in rails 4.
If you are not overriding registration constroller, you will need it, so my 1a step is stupid...
Add a new file under controllers folder named registrations_controller.rb with the following content:
class RegistrationsController < Devise::RegistrationsController
before_filter :configure_permitted_parameters
def new
if params.has_key?(:invitation_token)
inviter = User.where(:invitation_token => params[:invitation_token]).first
@invited_by = inviter.id
end
super
end
def create
super
if resource.save && params[:user].has_key?(:invited_by)
resource.invited_by = params[:user][:invited_by]
resource.save
end
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :invited_by
end
end
In new method, we are setting the extra field for the sign_up form. We are recovering the id of the inviter (who invites), using the token that comes from a param.
Creates method will save the user in the db. Before do it, we will get the hidden field from the form and add it to the user, in case that the user comes from an invitation.
In the view.html.erb (or whatever you are using) add the following line, inside the form:
<%= f.hidden_field :invited_by, :value => @invited_by %>
And that's it. Run the migration to add the new columns. Just go to http://example.org/users/sign_up?invitation_token=USER_TOKEN
Upvotes: 2
Reputation: 3412
You may want to do that manually by overriding the registration page of devise and allowing our new parameters to the model (attr_accessible rails 3 or params.require(:foo).permit)
First you should remove devise invitable as you will not use it for this approach i've searched and did not find a clean way to do it with devise_invitable.
Step 2: add attribute to the users table called invitation_token (this one is different from devise invitable as this will be unique per user and will be used to send invitation not used when receiving invitation)
and add to the user model (according to rails casts)
before_create :generate_invitation_token
def generate_invitation_token
self.invitation_token = Digest::SHA1.hexdigest([Time.now, rand].join)
end
by this each user will have a unique invitation_token
Step 3: now you can have a url like /signup/:invitation_token for to invite users which is unique per user (you should add this to routes and map it to the Devise::RegistrationsController#create)
Step 4: accept users and recognize who invited them on registration
Now we have to override the Devise::RegistrationsController#create and new and view
in the new you should find the user who invited. and add a virtual attribute that should reference the that user ie: inviter.id
and add a hidden_field to the registration form to set such attribute
Now in the create check for the availability of that attribute if present you can do what ever you want (add relation between users in your case).
And that's it i think If you need anything else comment and i will edit my answer to help you more
Upvotes: 4