From 766fe86a9f3b649aebff7604c9b2de677ddd71c2 Mon Sep 17 00:00:00 2001 From: Ryan Bates Date: Tue, 17 Nov 2009 11:46:27 -0800 Subject: [PATCH] support arrays being passed to 'can' to specify multiple actions or classes - closes #2 --- CHANGELOG.rdoc | 2 ++ lib/cancan/ability.rb | 8 +++++--- spec/cancan/ability_spec.rb | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index 6cf1e84..e6379a8 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -1,3 +1,5 @@ +* support arrays being passed to "can" to specify multiple actions or classes - see issue #2 + * adding "cannot?" method to ability, controller, and view which is inverse of "can?" - see issue #1 * BACKWARDS INCOMPATIBLE: use Ability#initialize instead of 'prepare' to set up abilities - see issue #4 diff --git a/lib/cancan/ability.rb b/lib/cancan/ability.rb index 8b6eb52..e227c65 100644 --- a/lib/cancan/ability.rb +++ b/lib/cancan/ability.rb @@ -4,14 +4,16 @@ module CanCan def can?(original_action, target) # TODO this could use some refactoring (@can_history || []).reverse.each do |can_action, can_target, can_block| + can_actions = [can_action].flatten + can_targets = [can_target].flatten 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_actions.include?(:manage) || can_actions.include?(action)) && (can_targets.include?(:all) || can_targets.include?(target) || can_targets.any? { |c| target.kind_of?(c) }) 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 << action if can_actions.include?(:manage) + block_args << (target.class == Class ? target : target.class) if can_targets.include?(:all) block_args << (target.class == Class ? nil : target) return can_block.call(*block_args) end diff --git a/spec/cancan/ability_spec.rb b/spec/cancan/ability_spec.rb index 0267198..b61d36b 100644 --- a/spec/cancan/ability_spec.rb +++ b/spec/cancan/ability_spec.rb @@ -85,4 +85,18 @@ describe CanCan::Ability do it "should offer cannot? method which is simply invert of can?" do @ability.cannot?(:tie, String).should be_true end + + it "should be able to specify multiple actions and match any" do + @ability.can [:read, :update], :all + @ability.can?(:read, 123).should be_true + @ability.can?(:update, 123).should be_true + @ability.can?(:count, 123).should be_false + end + + it "should be able to specify multiple classes and match any" do + @ability.can :update, [String, Array] + @ability.can?(:update, "foo").should be_true + @ability.can?(:update, []).should be_true + @ability.can?(:update, 123).should be_false + end end