Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should i implement authentication/authorization with multiple models using Rails?

I have 3 kind of users in my app: Club, Person, and Admin. Each one is very different from each other, which means they almost don't share any attributes except for the authentication data, so that's why i'd rather use 3 different models. Also, i want to enable a single authentication model for all these kinds of users, using Authlogic, and handle Authorization using CanCan.

Initially i thought of something like this.

class User < ActiveRecord::Base
 # This class has the email and password in order to be authenticated with Authlogic
end

And for each one i would have

class Club < User end
class Admin < User end

But then the User table would be cluttered with all the columns of the other kinds of users and they will remain null.

Another option would be

class User < ActiveRecord::Base
 # This class has the email and password in order to be authenticated with Authlogic
 belongs_to :role, :polymorphic => true
end

And for each kind of user, a role would be assigned. The problem is that accessing the properties of the method would be something like user.role.logo. One way i can think to solve this is by using delegate but still i don't know if that's the best option.

The question is, how would you suggest me to implement this? What would be the best way?

like image 825
acadavid Avatar asked Jan 18 '12 18:01

acadavid


2 Answers

Like you suggest, I would create a User model to handle authentication. Then you can create a one-to-one polymorphic relationship between the User model and your roles' models. Your User model will have to include role_type (which is a string) and role_id (which is an integer) attributes.

User.rb

class User < ActiveRecord::Base
  belongs_to :role, :polymorphic => true
end

Admin.rb

class Admin < ActiveRecord::Base
  has_one :role
end

You can test what class a user's role is and access its attributes. For example:

User.first.role.is_a? Admin
=> true
User.first.role.last_name
=> "Smith"
like image 186
niiru Avatar answered Oct 19 '22 11:10

niiru


I think you are trying to achieve role based authorization. Have a look at the wiki page in cancan.

https://github.com/ryanb/cancan/wiki/Role-Based-Authorization

like image 27
naren Avatar answered Oct 19 '22 11:10

naren