In Cancancan, why are merged rules still bound to the merged ability?

31 views Asked by At
class AbilityA
  include CanCan::Ability

  def initialize
    can :destroy, Event do |event|
      puts self.class.name # this will output "AbilityA" even when the rule is called by AbilityB after the merge.
      can? :access_edit_mode, event
    end
  end
end

class AbilityB
  include CanCan::Ability

  def initialize
    merge(AbilityA.new)

    can :access_edit_mode, Event do |event|
      puts "access edit mode from #{self.class.name}"
      true
    end
  end
end

AbilityB.new.can? :destroy, Event.last
# AbilityA
# => false

My understanding of merge would be that it would copy the can :destroy, Event from AbilityA in AbilityB, making AbilityB equivalent to:

class AbilityB
  include CanCan::Ability

  def initialize
      can :destroy, Event do |event|
        can? :access_edit_mode, event
      end
    end

    can :access_edit_mode, Event do |event|
      true
    end
  end
end

But... what actually happens:

The `can :destroy, Event` rule is still bound to AbilityA, which means that when it's calling `can? :access_edit_mode, event`, it is not found, because AbilityA does not have this rule, and the one from AbilityB is never called.

Is that expected behaviour? If so, any way to go around it? Should I not merge abilities and instead just define methods that would contain a bunch of abilities that I can then "compose"?
0

There are 0 answers