Skip to content
Michael Lin edited this page Nov 26, 2021 · 40 revisions

Add a role to a user

  1. To define a global role:

        user = User.find(1)
        user.add_role :admin
  2. To define a role scoped to a resource instance

        user = User.find(2)
        user.add_role :moderator, Forum.first
  3. To define a role scoped to a resource class

        user = User.find(3)
        user.add_role :moderator, Forum
  4. Starting from rolify 2.1, grant is a method alias for add_role

        user = User.find(4)
        user.grant :moderator, Forum.last

Role queries

  1. To check if a user has a global role:

        user = User.find(1)
        user.add_role :admin # sets a global role
        user.has_role? :admin
        => true
  2. To check if a user has any global role:

        user = User.find(1)
        user.add_role :admin
        user.add_role :moderator
        user.add_role :client
        
        user.has_any_role? :admin, :moderator
        => true
  3. To check if a user has a role scoped to a resource:

        user = User.find(2)
        user.add_role :moderator, Forum.first # sets a role scoped to a resource
        user.has_role? :moderator, Forum.first
        => true
        user.has_role? :moderator, Forum.last
        => false
        user.has_role? :moderator
        => false # returns false because the role is not global
        user.has_role? :moderator, :any
        => true # returns true because the user has at least one moderator role
  4. To check if a user has a role scoped to a resource class:

        user = User.find(3)
        user.add_role :moderator, Forum # sets a role scoped to a resource class
        user.has_role? :moderator, Forum
        => true
        user.has_role? :moderator, Forum.first
        => true
        user.has_role? :moderator, Forum.last
        => true
        user.has_role? :moderator
        => false
        user.has_role? :moderator, :any
        => true
  5. A global role has an implicit role for all resources:

        user = User.find(4)
        user.add_role :moderator # sets a global role
        user.has_role? :moderator, Forum.first
        => true
        user.has_role? :moderator, Forum.last
        => true
        user.has_role? :moderator, Forum
        => true
        user.has_role? :moderator, :any
        => true

Dynamic shortcuts

To be able to use dynamic shortcuts, you have to enable it first.

    user = User.find(1)
    user.add_role :admin # sets a global role
    user.is_admin?
    => true
    user.add_role :moderator, Forum.first
    user.is_moderator_of? Forum.last
    => false

Multiple role checking

  1. Check if the user has ALL specified roles

        user = User.find(1)
        user.add_role :admin # sets a global role
        user.add_role :moderator, Forum.first # sets a role scoped to a resource instance
        user.add_role :visitor, Forum # sets a role scoped to a resource class
        user.has_all_roles? :admin, { name: :moderator, resource: Forum.first }, { name: :visitor, resource: Forum }
        => true
        user.has_all_roles? :admin, { name: :moderator, resource: Forum.last }
        => false
        user.has_all_roles? :god, { name: :visitor, resource: Forum }
        => false
  2. Check if the user has ANY of the specified role(s)

        user = User.find(1)
        user.add_role :admin # sets a global role
        user.add_role :moderator, Forum.first # sets a role scoped to a resource
        user.add_role :visitor, Forum # set a role scoped to a resource class
        user.has_any_role? :admin, { name: :moderator, resource: Forum.first }, { name: :visitor, resource: Forum }
        => true
        user.has_any_role? :admin, { name: :moderator, resource: Forum.last }
        => true
        user.has_any_role? :god, { name: :visitor, resource: Forum }
        => true

Remove a role from a user

  1. Remove a global role

        user = User.find(1)
        user.remove_role :admin
        => true # if user previously had an admin role

    or (in case you get errors with the above method)

        user = User.find(1)
        user.remove_role "admin"
        => true # if user previously had an admin role
  2. Remove a role scoped to a resource instance

        user = User.find(2)
        user.remove_role :moderator, Forum.first
        => true # if user previously had a moderator role on Forum.first
  3. Remove a role scoped to a resource class

        user = User.find(3)
        user.remove_role :moderator, Forum
        => true # if user previously had a moderator role on Forum or any instance of Forum
  4. Starting from rolify 2.1, revoke is a method alias for remove_role

        user = User.find(4)
        user.revoke :moderator, Forum.first

Please note:

  • Trying to remove a global role where the user has a role with the same name on a resource will remove that scoped role (whatever the scope is)
  • Trying to remove a class scoped role where the user has an instance scoped role with the same name on a resource will remove that instance scoped role
  • Trying to remove a role scoped to a resource class where the user has a global role won't remove it
  • Trying to remove a role scoped to a resource instance where the user has a global role won't remove it

Finders methods

  1. Find users having a specific role

        User.with_role :admin
        # => [ list of users that have admin role ]
  2. Find users having all specified roles. Use a hash for resource scoped role

        User.with_all_roles :admin, { name: :moderator, resource: Forum }
        # => [ list of users that has admin _and_ moderator of forum roles ]
  3. Find users having any specified roles. Use a hash too for resource scoped role

        User.with_any_role :admin, { name: :moderator, resource: Forum.last }
        # => [ list of users that has admin _or_ moderator of the last forum roles ]
  4. Also, you could search by concatenating the search conditions as parameters.

        User.with_any_role(:admin, { name: :moderator, resource: Forum.last }, { name: :user, resource: Forum.last })
        # => [ list of users that has admin role without any Forum instance, moderator or user of the last forum roles ]

Resource role queries

Starting with rolify 3.0, you can search roles on instance level or class level resources.

  1. Instance level

        forum = Forum.first
        forum.roles
        # => [ list of roles that are only bound to a forum instance ]
        forum.applied_roles
        # => [ list of roles bound to a forum instance and to the Forum class ]
  2. Class level

        Forum.with_role(:admin)
        # => [ list of Forum instances that has the role "admin" bound to it ] 
        Forum.with_role(:admin, current_user)
        # => [ list of Forum instances that has the role "admin" bound to it and belongs to current_user roles ]
        
        Forum.find_roles
        # => [ list of roles that are bound to any Forum instance or to the Forum class ]
        Forum.find_roles(:admin)
        # => [ list of roles that are bound to any Forum instance or to the Forum class with "admin" as a role name ]
        Forum.find_roles(:admin, current_user)
        # => [ list of roles that are bound to any Forum instance or to the Forum class with "admin" as a role name and belongs to current_user roles ]
    
        Forum.find_roles(:any, current_user).where(resource_id: forum.id)
        # => [ list of roles that are bound to specific Forum instance and belongs to current_user roles ]

Finding roles through associations

user.rb

has_many :forums, through: :roles, source: :resource, source_type:  :Forum
has_many :moderated_forums, -> { where(roles: {name: :moderator}) }, through: :roles, source: :resource, source_type:  :Forum

let's you do

@user.forums 
# => [ all the forums where the @user has a role ]
@user.moderated_forums
# => [ all the forums where the @user has a moderator ]

forum.rb

has_many :users, -> { distinct }, through: :roles, class_name: 'User', source: :users
has_many :moderators, -> { where(:roles => {name: :moderator}) }, through: :roles, class_name: 'User', source: :users

let's you do

@forum.users
# => [ all the users that have a role in this forum ]
@forum.moderators
# => [ all the users that have a moderator role in this forum ]

Previous: Configuration