From cad425989e31b0e3f6012ac97daaaf172c9f7065 Mon Sep 17 00:00:00 2001 From: Ryan Bates Date: Mon, 19 Jul 2010 16:03:09 -0700 Subject: [PATCH] supporting deeply nested aliases - closes #98 --- CHANGELOG.rdoc | 2 ++ lib/cancan/ability.rb | 11 ++++++++++- lib/cancan/can_definition.rb | 11 ++--------- spec/cancan/ability_spec.rb | 7 +++++++ spec/spec.opts | 1 + 5 files changed, 22 insertions(+), 10 deletions(-) create mode 100644 spec/spec.opts diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index ef6d633..5ff5ab7 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -1,3 +1,5 @@ +* Supporting deeply nested aliases - see issue #98 + 1.2.0 (July 16, 2010) * Load nested parent resources on collection actions such as "index" (thanks dohzya) diff --git a/lib/cancan/ability.rb b/lib/cancan/ability.rb index d5c7002..51a95da 100644 --- a/lib/cancan/ability.rb +++ b/lib/cancan/ability.rb @@ -212,6 +212,15 @@ module CanCan end private + + # Accepts a hash of aliased actions and returns an array of actions which match. + # This should be called before "matches?" and other checking methods since they + # rely on the actions to be expanded. + def expand_actions(actions) + actions.map do |action| + aliased_actions[action] ? [action, *expand_actions(aliased_actions[action])] : action + end.flatten + end def can_definitions @can_definitions ||= [] @@ -219,7 +228,7 @@ module CanCan def matching_can_definition(action, subject) can_definitions.reverse.detect do |can_definition| - can_definition.expand_actions(aliased_actions) + can_definition.expanded_actions = expand_actions(can_definition.actions) can_definition.matches? action, subject end end diff --git a/lib/cancan/can_definition.rb b/lib/cancan/can_definition.rb index bd0b007..8ae40b6 100644 --- a/lib/cancan/can_definition.rb +++ b/lib/cancan/can_definition.rb @@ -5,6 +5,8 @@ module CanCan class CanDefinition # :nodoc: include ActiveSupport::Inflector attr_reader :block + attr_reader :actions + attr_writer :expanded_actions # The first argument when initializing is the base_behavior which is a true/false # value. True for "can" and false for "cannot". The next two arguments are the action @@ -18,15 +20,6 @@ module CanCan @block = block end - # Accepts a hash of aliased actions and returns an array of actions which match. - # This should be called before "matches?" and other checking methods since they - # rely on the actions to be expanded. - def expand_actions(aliased_actions) - @expanded_actions = @actions.map do |action| - aliased_actions[action] ? [action, *aliased_actions[action]] : action - end.flatten - end - def matches?(action, subject) matches_action?(action) && matches_subject?(subject) end diff --git a/spec/cancan/ability_spec.rb b/spec/cancan/ability_spec.rb index 4a49170..8a1431e 100644 --- a/spec/cancan/ability_spec.rb +++ b/spec/cancan/ability_spec.rb @@ -54,6 +54,13 @@ describe CanCan::Ability do @ability.can?(:destroy, 123).should == :modify_called end + it "should allow deeply nested aliased actions" do + @ability.alias_action :increment, :to => :sort + @ability.alias_action :sort, :to => :modify + @ability.can :modify, :all + @ability.can?(:increment, 123).should be_true + end + it "should return block result for action, object_class, and object for any action" do @ability.can :manage, :all do |action, object_class, object| [action, object_class, object] diff --git a/spec/spec.opts b/spec/spec.opts new file mode 100644 index 0000000..4e1e0d2 --- /dev/null +++ b/spec/spec.opts @@ -0,0 +1 @@ +--color