From 0b8b51b4fc70ac99b803930776337a0b08f54fa2 Mon Sep 17 00:00:00 2001 From: Ryan Bates Date: Mon, 16 Nov 2009 14:58:00 -0800 Subject: [PATCH] adding aliasing of actions --- lib/cancan/ability.rb | 39 ++++++++++++++++++++++++++----------- spec/cancan/ability_spec.rb | 10 ++++++++++ 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/lib/cancan/ability.rb b/lib/cancan/ability.rb index 7ae8f23..1dbc490 100644 --- a/lib/cancan/ability.rb +++ b/lib/cancan/ability.rb @@ -4,30 +4,47 @@ module CanCan base.extend ClassMethods end - def can?(action, target) - self.class.can_history.reverse.each do |can_action, can_target, can_block| - if (can_action == :manage || can_action == action) && (can_target == :all || can_target == target || target.kind_of?(can_target)) - if can_block.nil? - return true - else - block_args = [] - block_args << action if can_action == :manage - block_args << (target.class == Class ? target : target.class) if can_target == :all - block_args << (target.class == Class ? nil : target) - return can_block.call(*block_args) + def can?(original_action, target) + (self.class.can_history || []).reverse.each do |can_action, can_target, can_block| + possible_actions_for(original_action).each do |action| + if (can_action == :manage || can_action == action) && (can_target == :all || can_target == target || target.kind_of?(can_target)) + if can_block.nil? + return true + else + block_args = [] + block_args << action if can_action == :manage + block_args << (target.class == Class ? target : target.class) if can_target == :all + block_args << (target.class == Class ? nil : target) + return can_block.call(*block_args) + end end end end false end + def possible_actions_for(initial_action) + actions = [initial_action] + (self.class.aliased_actions || []).each do |target, aliases| + actions += possible_actions_for(target) if aliases.include? initial_action + end + actions + end + module ClassMethods attr_reader :can_history + attr_reader :aliased_actions def can(action, target, &block) @can_history ||= [] @can_history << [action, target, block] end + + def alias_action(*args) + @aliased_actions ||= {} + target = args.pop[:to] + @aliased_actions[target] = args + end end end end diff --git a/spec/cancan/ability_spec.rb b/spec/cancan/ability_spec.rb index c31d57e..009e0c5 100644 --- a/spec/cancan/ability_spec.rb +++ b/spec/cancan/ability_spec.rb @@ -2,6 +2,8 @@ require File.dirname(__FILE__) + '/../spec_helper' class Ability include CanCan::Ability + alias_action :update, :destroy, :to => :modify + can :read, :all can :read, Symbol do |sym| sym @@ -12,6 +14,9 @@ class Ability can :manage, Array do |action, object| [action, object] end + can :modify, :all do |object_class, object| + :modify_called + end end class AdminAbility @@ -52,6 +57,11 @@ describe Ability do @ability.can?(:stuff, [1, 2]).should == [:stuff, [1, 2]] @ability.can?(:stuff, Array).should == [:stuff, nil] end + + it "should alias update or destroy actions to modify action" do + @ability.can?(:update, 123).should == :modify_called + @ability.can?(:destroy, 123).should == :modify_called + end end describe AdminAbility do