Search code examples
ruby-on-rails-3devisecancanbefore-filter

Rails 3 CanCan Authorizing Scoped Ownership


I'm building a school systems where instructors can manage classrooms in scope of their respective schools.

I have the following ability setup to match:

class Ability
  include CanCan::Ability

  #define the user ability
  def initialize(user)
    user ||= User.new # guest user (not logged in)    
    if user.has_role? :instructor
      can :manage, Classroom do |classroom|
        classroom.new_record? && classroom.school_id == user.school_id || classroom.instructor == user
      end
    end
  end 

end

In theory this should enable instructors to manage new records which won't have their relationship with the instructor setup so long as both the instructor and the new classroom belong to the same school.

In my classroom new action I build the classroom from the parent School to accommodate this @classroom = @school.classrooms.build. This initializes the new Classroom record with a school_id enabling the instructor to to thereby manage the record. However in my classrooms controller I call load_and_authorize_resource which authorizes the instructor before the school to classroom relationship gets established and a CanCan authorization exception is thrown.

Is there any way around this?


Solution

  • CanCan is probably checking abilities before the association with the school is built. You could break out the create and manage permissions explicitly:

    can :create, Classroom
    can :manage, Classroom, instructor_id: user.id
    

    and then check that the classroom belongs to the instructor's school in a validation.