Search code examples
ruby-on-railscancancancancan

Rails 4 - cancancan - defining abilities


Is it possible to define a CanCanCan ability by reference to another ability?

For example, I have models called Project and Project Question.

I want to allow a class of users to read projects and then if they can read the projects then they can create project questions.

I have defined the abilities for users to read Projects as:

can :read, Project, 
      {:active => true, 
       :closed => false,
       :sweep => { :disclosure => { :allusers => true }}
      } 

Now I'd like to define an ability to create a project question. I'm wondering whether you can say something along the lines of:

if can :read, Project, can :create, ProjectQuestion

I have also tried:

can [:create, :read], ProjectQuestion do |pq3|
        if can :read Project 
        end

Is it possible to define one ability by reference to another one?

PS: this is not a duplicate of my other question about cancancan which is asking for help with syntax in expressing ability by reference to attributes in the db.


Solution

  • Assuming there's has_many/belongs_to type of assciation you can easily do it this way:

    can [:create, :read], ProjectQuestion do |project_question|
      can? :read, project_question.project
    end
    

    Mind that you'll have to assign a project_id to the new project_question before checking the ability.

    So in your controller/views you cannot do

    can? :create, ProjectQuestion.new
    

    as it will always return false. You will have to do:

    can? :create, some_project.project_questions.new