-1

Need Help! :)


Use Case: Admin can create another admin when he have role of "SuperAdmin", Admin Can also Create "Agents"

Roles for Admin Model:

  1. SuperAdmin
  2. Admin

Admin can create both the roles can create "Agents"


Agent can create "User" but he will not be able to create "Agents" and he should not see users created by other Agents. He has only one Role - "Agent"


Now the problem is : how to initialize "admin", "agent" & "user" in Ability as they are are 3 different models ?

class Ability
  def initialize(user)
    user ||= User.new # guest user (not logged in)
    can :read, Photo, Photo.unowned do |photo|
      photo.groups.empty?
    end
  end
end

Note: Users are under Agent and Agents are under Admin.. I need them to be different models

Syed
  • 15,657
  • 13
  • 120
  • 154
  • Maybe you should have a single common model 'User' and associate roles to them? – code-gijoe Sep 26 '12 at 20:57
  • @code-gijoe thanks for your comment - as mentioned above, i need them in a different table. – Syed Sep 27 '12 at 05:57
  • 1
    Can you explain a little why you need each role in a different table? That will help us better answer your question I think. @code-gijoe's reference to Single Table Inheritance (or Polymorphic Associations) in his answer is the best way and will allow you to have separate model classes for each role. But maybe we're missing some detail about your use-case and needs? – GorrillaMcD Sep 27 '12 at 18:29

2 Answers2

2

Well, I suggest you define your role in a base model like 'User'. Then use this to create a user hierarchy. Your model should initialize the role. Say you create a User, then the role should be something like :user. Any user that tries to perform an action will (if your controller is well defined) go through 'initialize'.

The initialize method is not to initialize the role but the rules for that particular role.

class Ability
   def initialize(user)
      user ||= User.new # guest user (not logged in)

      if user.role == :admin
         can :read, Photo, Photo.unowned do |photo|
           photo.groups.empty?
      elsif user.role == :agent 
         # rules for agents
      else
         # rules for others
      end
  end
end
Community
  • 1
  • 1
code-gijoe
  • 6,949
  • 14
  • 67
  • 103
0

What you need is nested attributes, which will allow you to have a single User model with separate models for each type of user (if your various roles differ a lot in the types of information they require, that is). For example, agents might have education, field or region, and personal website attributes while normal users have company, favorite quote, and whatever else.

The User model would have information all roles require (email, password, name, role) while models for each role would have information specific to that role. This way, you can follow the documentation for CanCan to do your authorization, but still have role-specific information.

There is a great railscast on nested_attributes: http://railscasts.com/episodes/196-nested-model-form-part-1 (part 1) and http://railscasts.com/episodes/197-nested-model-form-part-2

Note: These railscast episodes are specific to making question and answer functionality, but the concepts they teach can apply directly to your situation.

GorrillaMcD
  • 1,884
  • 1
  • 14
  • 22
  • thanks to write this to me, the concept is all together is different, i just want to know how can i initialize different role here - **def initialize(user)** – Syed Sep 27 '12 at 06:09
  • Yes, I understand. What I was trying to tell you is that you don't need a separate model for each role. In fact, CanCan wasn't designed to work that way. I know it's different from what you're doing now, but it's a better way to do it in my opinion and solves your problem. – GorrillaMcD Sep 27 '12 at 15:22