简体   繁体   中英

CanCan, what does passing a block to the can method in Ability#initialize do?

This is my Ability.rb file:

class Ability
  include CanCan::Ability

  def initialize(user)
    user.permissions.each do |permission|
      can permission.action.to_sym,
          permission.thing_type.constantize {|thing| thing.nil? || permission.thing.nil? || permission.thing_id == thing.id}
    end
  end
end

thing is a polymorphic association. I'm trying to understand how passing a block to can works. I've searched throughout the wiki for CanCan but haven't been able to find an explanation.

Passing a block to cancan allows you to implement more complicated permission checks that depend on the state of the object itself.

When it's just attributes on the object you want to check then you don't need a block:

can :read, Project, :active => true

allows a user to only read active projects. If you need to call project's editable method then you could instead do

can :read, Project do |project|
  project.editable?
end

At the point that cancan checks whether you can read a particular project (ie when the before_filter fires or you call `can? :read, some_project) then the block gets called

There's a page about this on the wiki: Defining abilities with blocks .

In your case it looks like the intent is that the permission object can either grant access to a whole class (if thing_type is set but thing_id is null) or to a specific instance of the class.

However the code you've posted doesn't actually do this. Of the 2 ways of passing a block, {} binds more tightly than do...end so the block isn't passed to can at all. It is instead passed to constantize , which ignores it. You could disambiguate this by using parentheses, or by using do...end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM