Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Proc as Rule condition #773

Open
wants to merge 3 commits into from

2 participants

@timoschilling

allow to use Proc (or other Objects that respond to call) as a Rule condition, so you can do slow stuff in it, with don't need to be execute each time the Ability Class will be instantiate.

can :manage, Region, :_id.in => ->{ user.region.self_and_child_ids }
@xhoy

Thanks for your submission! The ryanb/cancan repository has been inactive since Sep 06, 2013.
Since only Ryan himself has commit permissions, the CanCan project is on a standstill.

CanCan has many open issues, including missing support for Rails 4. To keep CanCan alive, an active fork exists at cancancommunity/cancancan. The new gem is cancancan. More info is available at #994.

If your pull request or issue is still applicable, it would be really appreciated if you resubmit it to CanCanCan.

We hope to see you on the other side!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 25 additions and 3 deletions.
  1. +19 −3 lib/cancan/rule.rb
  2. +6 −0 spec/cancan/rule_spec.rb
View
22 lib/cancan/rule.rb
@@ -3,7 +3,7 @@ module CanCan
# it holds the information about a "can" call made on Ability and provides
# helpful methods to determine permission checking and conditions hash generation.
class Rule # :nodoc:
- attr_reader :base_behavior, :subjects, :actions, :conditions
+ attr_reader :base_behavior, :subjects, :actions
attr_writer :expanded_actions
# The first argument when initializing is the base_behavior which is a true/false
@@ -20,6 +20,22 @@ def initialize(base_behavior, action, subject, conditions, block)
@block = block
end
+ # Process the conditions that are a Proc or a callable Object
+ def conditions
+ case @conditions
+ when Array
+ @conditions.map do |condition|
+ condition.respond_to?(:call) ? condition.call : condition
+ end
+ when Hash
+ @conditions.each_with_object({}) do |(key, condition), processed_conditions|
+ processed_conditions[key] = condition.respond_to?(:call) ? condition.call : condition
+ end
+ else
+ @conditions
+ end
+ end
+
# Matches both the subject and action, not necessarily the conditions
def relevant?(action, subject)
subject = subject.values.first if subject.class == Hash
@@ -35,7 +51,7 @@ def matches_conditions?(action, subject, extra_args)
elsif @conditions.kind_of?(Hash) && subject.class == Hash
nested_subject_matches_conditions?(subject)
elsif @conditions.kind_of?(Hash) && !subject_class?(subject)
- matches_conditions_hash?(subject)
+ matches_conditions_hash?(subject, conditions)
else
# Don't stop at "cannot" definitions when there are conditions.
@conditions.empty? ? true : @base_behavior
@@ -98,7 +114,7 @@ def matches_subject_class?(subject)
# This behavior can be overriden by a model adapter by defining two class methods:
# override_matching_for_conditions?(subject, conditions) and
# matches_conditions_hash?(subject, conditions)
- def matches_conditions_hash?(subject, conditions = @conditions)
+ def matches_conditions_hash?(subject, conditions)
if conditions.empty?
true
else
View
6 spec/cancan/rule_spec.rb
@@ -49,4 +49,10 @@
@conditions = {}
@rule.should_not be_unmergeable
end
+
+ it "should execute proc conditions" do
+ @conditions[:foo] = proc { 1 }
+ @conditions[:bar] = 2
+ @rule.conditions.should == {:foo => 1, :bar => 2}
+ end
end
Something went wrong with that request. Please try again.