Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Devise add role based on signup path

I'm building a Rails 3 system where I need to give users specific roles based on the path they take to sign up on the site. I am using Devise and Cancan.

So for instance, the path

new-fundraiser (or /users/new/fundraiser)

Needs to set user.fundraiser = true on user creation, and

new-charity-user (or /users/new/charity)

Needs to set user.charity_owner = true on user creation.

What is the easiest / best-practice way to accomplish this using Devise and Cancan?

like image 559
Houen Avatar asked Jun 05 '11 12:06

Houen


2 Answers

Thanks for the great answer @andrew-nesbitt. The original question suggests that @Houen had already customized Devise somewhat. Here's a slightly tweaked answer that works with an out-of-the-box Devise set-up and many-to-many user-roles CanCan set-up.

First, in your routes, add:

devise_scope :user do
    match "/users/sign_up/:initial_role" => 'devise/registrations#new', :as => 'new_user_with_role'
end

You can then refer to this route like:

<%= link_to 'here', new_user_with_role_path(:initial_role => 'human') %>

Then, in your User model add

attr_accessible :initial_role

def initial_role=(role_name)
    @initial_role = role_name
    role = Role.find_by_name(role_name)
    self.roles << role
end

def initial_role
    @initial_role
end

And finally in views/devise/registrations/new.html.erb add

<%= f.hidden_field :initial_role, :value => params[:initial_role] %>
like image 84
cailinanne Avatar answered Oct 11 '22 16:10

cailinanne


I would set up a route like:

match "/users/new/:role", :to => 'users#new'

In your user model I'd add an accessor:

class User < ActiveRecord::Base
  def role=(role_name)
    @role = role_name
    case role_name
    when 'charity'
      self.charity_owner = true
    when 'fundraiser'
      self.fundraiser = true
    else
      # raise some exception
    end
  end

  def role
    @role
  end
end

Then in your users#new.html.erb form add a hidden field:

<%= form.hidden_field :role, :value => params[:role] %>

Then your won't need to change your controller code at all.

like image 44
Andrew Nesbitt Avatar answered Oct 11 '22 15:10

Andrew Nesbitt