Reputation: 1816
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.
Upvotes: 1
Views: 1741
Reputation: 84172
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
Upvotes: 1