diff --git a/lib/cancan/ability.rb b/lib/cancan/ability.rb index 20ab6297..33d04b0b 100644 --- a/lib/cancan/ability.rb +++ b/lib/cancan/ability.rb @@ -202,12 +202,13 @@ def has_raw_sql?(action, subject) relevant_rules(action, subject).any?(&:only_raw_sql?) end - # Copies all rules of the given +CanCan::Ability+ and adds them to +self+. + # Copies all rules and aliased actions of the given +CanCan::Ability+ and adds them to +self+. # class ReadAbility # include CanCan::Ability # # def initialize # can :read, User + # alias_action :show, :index, to: :see # end # end # @@ -216,6 +217,7 @@ def has_raw_sql?(action, subject) # # def initialize # can :edit, User + # alias_action :create, :update, to: :modify # end # end # @@ -223,11 +225,35 @@ def has_raw_sql?(action, subject) # read_ability.can? :edit, User.new #=> false # read_ability.merge(WritingAbility.new) # read_ability.can? :edit, User.new #=> true + # read_ability.aliased_actions #=> [:see => [:show, :index], :modify => [:create, :update]] # + # If there are collisions when merging the +aliased_actions+, the actions on +self+ will be + # overwritten. + # + # class ReadAbility + # include CanCan::Ability + # + # def initialize + # alias_action :show, :index, to: :see + # end + # end + # + # class ShowAbility + # include CanCan::Ability + # + # def initialize + # alias_action :show, to: :see + # end + # end + # + # read_ability = ReadAbility.new + # read_ability.merge(ShowAbility) + # read_ability.aliased_actions #=> [:see => [:show]] def merge(ability) ability.rules.each do |rule| add_rule(rule.dup) end + @aliased_actions = aliased_actions.merge(ability.aliased_actions) self end diff --git a/spec/cancan/ability_spec.rb b/spec/cancan/ability_spec.rb index f62fab7f..fbccc108 100644 --- a/spec/cancan/ability_spec.rb +++ b/spec/cancan/ability_spec.rb @@ -564,6 +564,35 @@ class Container < Hash expect(@ability.send(:rules).size).to eq(2) end + it 'adds the aliased actions from the given ability' do + @ability.alias_action :show, to: :see + (another_ability = double).extend(CanCan::Ability) + another_ability.alias_action :create, :update, to: :manage + + @ability.merge(another_ability) + expect(@ability.aliased_actions).to eq( + read: %i[index show], + create: %i[new], + update: %i[edit], + manage: %i[create update], + see: %i[show] + ) + end + + it 'overwrittes the aliased actions with the value from the given ability' do + @ability.alias_action :show, :index, to: :see + (another_ability = double).extend(CanCan::Ability) + another_ability.alias_action :show, to: :see + + @ability.merge(another_ability) + expect(@ability.aliased_actions).to eq( + read: %i[index show], + create: %i[new], + update: %i[edit], + see: %i[show] + ) + end + it 'can add an empty ability' do (another_ability = double).extend(CanCan::Ability)