class DeclarativePolicy::ManifestCondition

In contrast to a Condition, a ManifestCondition contains a Condition and a context object, and is capable of calculating a result itself. This is the return value of Base#condition.

Public Class Methods

new(condition, context) click to toggle source
# File lib/declarative_policy/condition.rb, line 34
def initialize(condition, context)
  @condition = condition
  @context = context
end

Public Instance Methods

cached?() click to toggle source

Whether we've already computed this condition.

# File lib/declarative_policy/condition.rb, line 47
def cached?
  @context.cached?(cache_key)
end
pass?() click to toggle source

The main entry point - does this condition pass? We reach into the context's cache here so that we can share in the global cache (often RequestStore or similar).

# File lib/declarative_policy/condition.rb, line 42
def pass?
  @context.cache(cache_key) { @condition.compute(@context) }
end
score() click to toggle source

This is used to score Rule::Condition. See Rule::Condition#score and Runner#steps_by_score for how scores are used.

The number here is intended to represent, abstractly, how expensive it would be to calculate this condition.

See cache_key for info about @condition.scope.

# File lib/declarative_policy/condition.rb, line 58
def score
  # If we've been cached, no computation is necessary.
  return 0 if cached?

  # Use the override from condition(score: ...) if present
  return @condition.manual_score if @condition.manual_score

  # Global scope rules are cheap due to max cache sharing
  return 2 if  @condition.scope == :global

  # "Normal" rules can't share caches with any other policies
  return 16 if @condition.scope == :normal

  # otherwise, we're :user or :subject scope, so it's 4 if
  # the caller has declared a preference
  return 4 if @condition.scope == DeclarativePolicy.preferred_scope

  # and 8 for all other :user or :subject scope conditions.
  8
end

Private Instance Methods

cache_key() click to toggle source

This method controls the caching for the condition. This is where the condition(scope: …) option comes into play. Notice that depending on the scope, we may cache only by the user or only by the subject, resulting in sharing across different policy objects.

# File lib/declarative_policy/condition.rb, line 85
def cache_key
  @cache_key ||=
    case @condition.scope
    when :normal  then "/dp/condition/#{@condition.key}/#{user_key},#{subject_key}"
    when :user    then "/dp/condition/#{@condition.key}/#{user_key}"
    when :subject then "/dp/condition/#{@condition.key}/#{subject_key}"
    when :global  then "/dp/condition/#{@condition.key}"
    else raise 'invalid scope'
    end
end
subject_key() click to toggle source
# File lib/declarative_policy/condition.rb, line 100
def subject_key
  Cache.subject_key(@context.subject)
end
user_key() click to toggle source
# File lib/declarative_policy/condition.rb, line 96
def user_key
  Cache.user_key(@context.user)
end