Search code examples
ruby-on-railsrubydevisecancancanrolify

Rolify: Can a User assign a specific Resource Role to another User?


I'm trying to determine whether this flow is possible when using Rolify (with Devise and CanCanCan)... And, if so, how it would be implemented:

I have a class, Shop, which belongs to User. I'd like the user who created a respective Shop instance to be able to assign a Rolify role (:manager) to any user (N.B. any user who created an instance should be able to assign the role - not just a user who has the role :admin).

I know this can be achieved via the rails console through the add_role command (using, as an example, a Shop instance with id: 5):

user.add_role :manage, Shop.find(5)

But I'm not clear on whether or not this can be done programmatically by individual users - where a user can assign the role to another user. Specifically, by selecting the user from a searchable dropdown form and assigning the role on submit.

Though I don't yet have any code that's worth showing / helpful to show, I'm hoping to get direction here as to how best to approach this issue (e.g., should the action be defined in shops_controller.rb or in its own controller?). Also, would it be better to scrap using Rolify for this altogether and create a join table for shops_managers?

If it helps, here's the Ability.rb class:

    class Ability
      include CanCan::Ability

      def initialize(user)
        if user
          if user.has_role? :admin
            can :manage, :all
          else
            can [:edit, :update], Shop.with_role(:manager, user)
            can :manage, Shop, :user_id => user.id
            can :manage, User, id: user.id
            can :read, :all
          end
        end
      end

Thanks much!


Solution

  • You don't need join table to store shops_managers. You have a role model:
    Role(id: integer, name: string, resource_id: integer, resource_type: string, created_at: datetime, updated_at: datetime)
    It is perfectly fine to add the role in shops#create doing something like:

    if @shop.save
      #some code
      @current_user.add_role :manager, @shop  
      #some more code
    end
    

    If you want to manage the roles it should be done in some other controller.. probably in admins namespace.