Rails Devise Adds Role Based on Registration Path

I am building a Rails 3 system where I need to provide users with specific roles based on the path that they take to register on the site. I use Devise and Cancan.

So, for example, the way

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

It is required to set user.fundraiser = true when creating the user and

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

It is required to set user.charity_owner = true when creating the user.

What is the easiest / best way to do this using Devise and Cancan?

+6
source share
3 answers

I would set a route, for example:

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

In your user model, I would add an accessory:

 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 user group # new.html.erb add a hidden field:

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

Then you do not need to change the controller code at all.

+6
source

Thanks for the great answer @ andrew-nesbitt. The initial question suggests that @Houen has already configured Devise somewhat. Here's a slightly modified answer that works with the Devise pre-configured and many-to-many CanCan user roles.

First in your routes add:

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

Then you can access this route, for example:

 <%= 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 / devize / registration / new.html.erb add

 <%= f.hidden_field :initial_role, :value => params[:initial_role] %> 
+10
source

Using ready-made Devise and CanCan, I set up my user "roles" in accordance with the Rails Casts # 189 "Embedded Association". However, I was not able to get @cailinanne's answer to work with my setup, as Roles was supposed to have a different approach. If anyone has a similar issue, here is a much less elegant / robust approach, which is borrowed from @cailinanne's answer. It has one advantage: no need to modify the User model.

Use the devise_scope route and the link_to code provided by @cailinanne. Skip the changes to the user model. Finally, use the following code in views / development / registration / new.html.erb:

  <% if params[:initial_role] == "admin" %> <%= hidden_field_tag "user[roles][]", :admin %> <% elsif params[:initial_role] == "moderator" %> <%= hidden_field_tag "user[roles][]", :moderator %> <% elsif params[:initial_role] == "author" %> <%= hidden_field_tag "user[roles][]", :author %> <% end %> 

This code replaces the check_box_tag code provided in the Rails Cast code.

It definitely needs extra work. I will translate the if-elsif-elsif logic into the controller at some point and reference it to User.ROLES so that it does not break if I add / remove a role. But this will help you get the initial role assignment if you adopted the Rails Cast role approach.

+1
source

Source: https://habr.com/ru/post/889815/


All Articles