#cannot with hash coditions acts as #can in #accessible_by #71

funny-falcon opened this Issue May 16, 2010 · 5 comments


None yet

2 participants

class Ability
  include CanCan::Ability
  def initialize(user)
    if user.god?
      cannot :do_blocking, User, :id=>user.id
      cannot :do_blocking, User

>> g = User.find_by_god(true); ga = Ability.new(g); g.id
SELECT * FROM "users" WHERE ("users"."god" = 't') LIMIT 1
=> 1
>> User.accessible_by(ga, :do_blocking)
SELECT * FROM "users" WHERE ("users"."id" = 1)
ryanb commented May 20, 2010

Hmm, performing a not condition may be difficult here. I may just end up raising an exception on cannot calls saying it's not supported with accessible_by. Unless someone else has another suggestion.


I've implemented concerning of multiple can and cannot conditions both in can? and accessible_by in my fork http://github.com/funny-falcon/cancan .
What it does: while checking can? it pass through not matching conditions and stops only on matching.
@ability = Object.new
@ability.can :read, :all
@ability.cannot :read, Integer do |i| i > 5 end
@ability.can :read, Integer do |i| i > 10 && i < 15 end
@ability.can? :read, 11 # => true
@ability.can? :read, 7 # => false
@ability.can? :read, 4 # => true

It cause some backward incompatibility though
@ability.can :read, :all
@ability.can :read, Integer do |i| i > 5 end
@ability.can? :read, 6 # => true in both
@ability.can? :read, 4 # => false in mine and true in your's

It can generate SQL for complex conditions, concerning cannot and can semantic:
@ability.can :read, obj
@ability.can :manage, obj, :id => 1
@ability.can :update, obj, :manager_id => 1
@ability.cannot :update, obj, :self_managed => true

@ability.sql_conditions(:update, obj) # => 'not (self_managed=true) AND ((manager_id=1) OR (id=1))'

I understood performance impact and some level of incompatibility, so that it just a "feature suggestion".

ryanb commented May 21, 2010

Wow, it looks like you put a lot of work into this, thank you! I'll definitely check it out and consider pulling it in.


fork merged and some errors fixed.

ryanb commented Jul 21, 2010

updating changelong with support for multiple can calls in accessible_by - closed by 1659f21

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment