user3443619
user3443619

Reputation: 119

How do rails app have invite your friends custom url?

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

Answers (2)

Seoman
Seoman

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

khaled_gomaa
khaled_gomaa

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

Related Questions