Search code examples
ruby-on-railsrubycancancancancan

Difference between CanCanCan "index" rule with and without a block


Are these two statements basically the same? If they aren't then what should the second version look like? And what's going on under the covers?

can :index, User, approved: true

can :index, User do |user|
  user.approved?
end

I'm not able to get "block" versions of tests working. Everything else works fine.. but blocks don't work. I'm clearly doing something wrong, so I'm trying to understand. Thanks.


Solution

  • Rules with blocks are used when an instance is passed to the rule:

    can?(:show, User.first)
    

    The index action is special because there's no instance of User to pass to the rule, you are not loading a specific user, but multiple.

    So,

    can :index, User, approved: true
    

    When the UserController#index action is hit, assuming you have load_and_authorize_resource (or similar in place), it will load in @users all the users with approved: true. If there are no conditions, all users will be loaded. It's straightforward.

    Now,

    can :index, User do |user|
      user.approved?
    end
    

    If a rule has a block and the instance is not passed to it (as I said above), the rule will always return true as in authorized, BUT no users will be loaded.

    More explanations, here.