Reputation: 8597
I was wondering what would be the most logical way of handling which type of user a user would sign up?
When a user registered their say:
name, email, password
They get redirected to another page asking which role they're interested in signing up:
business or resident
Should I just assign a new column in users table in their database? string :role
? Or should I create a new table? And what gem would work best for handling something like this? Eventually I would want to output different view layouts depending on user's role
Thanks
Upvotes: 1
Views: 214
Reputation: 5352
As I stated the best gem for something like this would be CanCan because it allows you to alter your roles to how you want. With the ability to filter out particular actions for different roles. To go about this I suggest to do the following:
1. Adding Roles
rails g scaffold Role name:string
2. HABTM relationship between roles and users
rails generate migration UsersHaveAndBelongsToManyRoles
class UsersHaveAndBelongsToManyRoles < ActiveRecord::Migration
def self.up
create_table :roles_users, :id => false do |t|
t.references :role, :user
end
end
def self.down
drop_table :roles_users
end
end
3.Modify the Role model, so it looks like the following
class Role < ActiveRecord::Base
has_and_belongs_to_many :users
end
4. Altering User model
Add :role_ids to attr_accessible so that you can then add the following method to identify the role of a particular user.
class User < ActiveRecord::Base
has_and_belongs_to_many :roles
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :username, :password, :password_confirmation,
:remember_me, :role_ids
def role?(role)
!!self.roles.find_by_name(role.to_s.camelize)
end
end
5. Seeding roles
%w(Business Administrator Resident).each { |role| Role.create!(:name => role) }
The above is a literal array of the roles
So you could do something like this as an example:
b = User.create!(:email => "[email protected]",
:password => "pass",
:password_confirmation => "pass",
)
b.roles << Role.first
b.save
6. Registration form
Your registration form may look like the following this is an example:
<%= form_for(@user) do |f| %>
<% if @user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@user.errors.count, "error") %>
prohibited this user from being saved:</h2>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<% if @current_method == "new" %>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<% end %>
<% for role in Role.find(:all) %>
<div>
<%= check_box_tag "user[role_ids][]",
role.id, @user.roles.include?(role) %>
<%= role.name %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The above form will allow the user to select their role.
6. Migrate your database
rake db:migrate
7. Defining permissions using CanCan
Generate the ability
class using - rails g cancan:ability
Ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user
if user.role? :administrator
can :manage, :all
can :manage, User
elsif user.role? :business
can [:create, :new], Business
can [:show, :update], User, :id => user.id
else user.role? :resident
can [:show, :update], User, :id => user.id
end
end
end
As you stated you want to show different parts of a page to different users. So you may have on a particular view the following if-else
Example View
<% if current_user.role? business %>
#Show stuff visible to business user
<% else current_user.role? resident %>
#Show stuff visible to resident user
<% end %>
Hopefully this gives some clarity on what you want to do
Filter example:
def admin_business_user
redirect_to dashboard_path, :notice =>
'You must be an admin to do that!'
unless current_user.role? :administrator || :business
end
Upvotes: 4
Reputation: 73
If you are only going to have 2 roles then it is probably easiest to add a column to your users model.
rails generate migration add_business_to_users business:boolean
Then in the migration add a default to this column like
class AddBusinessToUsers < ActiveRecord::Migration
def change
add_column :users, :business, :boolean, default: false
end
end
Once you have migrated this to your database you have everything you need for 2 roles. For example you can always use
user.business? #This will be true for a user that is a business and false for resident
What you are effectively assuming is that every user that is not a business is a resident.
If you are going to have more roles then it makes sense to have a separate roles model or use a gem like cancan.
Upvotes: 1