Class: DeclarativePolicy::Step
- Inherits:
-
Object
- Object
- DeclarativePolicy::Step
- Defined in:
- lib/declarative_policy/step.rb
Overview
This object represents one step in the runtime decision of whether an ability is allowed. It contains a Rule and a context (instance of DeclarativePolicy::Base), which contains the user, the subject, and the cache. It also contains an “action”, which is the symbol :prevent or :enable.
Instance Attribute Summary collapse
-
#action ⇒ Object
readonly
Returns the value of attribute action.
-
#context ⇒ Object
readonly
Returns the value of attribute context.
-
#rule ⇒ Object
readonly
Returns the value of attribute rule.
Instance Method Summary collapse
-
#==(other) ⇒ Object
In the flattening process, duplicate steps may be generated in the same rule.
- #enable? ⇒ Boolean
-
#flattened(roots) ⇒ Object
This rather complex method allows us to split rules into parts so that they can be sorted independently for better optimization.
-
#initialize(context, rule, action) ⇒ Step
constructor
A new instance of Step.
- #pass? ⇒ Boolean
- #prevent? ⇒ Boolean
- #repr ⇒ Object
-
#score ⇒ Object
In the runner, steps are sorted dynamically by score, so that we are sure to compute them in close to the optimal order.
- #with_action(action) ⇒ Object
Constructor Details
#initialize(context, rule, action) ⇒ Step
Returns a new instance of Step.
12 13 14 15 16 |
# File 'lib/declarative_policy/step.rb', line 12 def initialize(context, rule, action) @context = context @rule = rule @action = action end |
Instance Attribute Details
#action ⇒ Object (readonly)
Returns the value of attribute action.
10 11 12 |
# File 'lib/declarative_policy/step.rb', line 10 def action @action end |
#context ⇒ Object (readonly)
Returns the value of attribute context.
10 11 12 |
# File 'lib/declarative_policy/step.rb', line 10 def context @context end |
#rule ⇒ Object (readonly)
Returns the value of attribute rule.
10 11 12 |
# File 'lib/declarative_policy/step.rb', line 10 def rule @rule end |
Instance Method Details
#==(other) ⇒ Object
In the flattening process, duplicate steps may be generated in the same rule. This allows us to eliminate those (see Runner#steps_by_score and note its use of a Set)
21 22 23 |
# File 'lib/declarative_policy/step.rb', line 21 def ==(other) @context == other.context && @rule == other.rule && @action == other.action end |
#enable? ⇒ Boolean
44 45 46 |
# File 'lib/declarative_policy/step.rb', line 44 def enable? @action == :enable end |
#flattened(roots) ⇒ Object
This rather complex method allows us to split rules into parts so that they can be sorted independently for better optimization
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/declarative_policy/step.rb', line 54 def flattened(roots) case @rule when Rule::Or # A single `Or` step is the same as each of its elements as separate steps @rule.rules.flat_map { |r| Step.new(@context, r, @action).flattened(roots) } when Rule::Ability # This looks like a weird micro-optimization but it buys us quite a lot # in some cases. If we depend on an Ability (i.e. a `can?(...)` rule), # and that ability *only* has :enable actions (modulo some actions that # we already have taken care of), then its rules can be safely inlined. steps = @context.runner(@rule.ability).steps.reject { |s| roots.include?(s) } if steps.all?(&:enable?) # in the case that we are a :prevent step, each inlined step becomes # an independent :prevent, even though it was an :enable in its initial # context. steps.map! { |s| s.with_action(:prevent) } if prevent? steps.flat_map { |s| s.flattened(roots) } else [self] end else [self] end end |
#pass? ⇒ Boolean
81 82 83 |
# File 'lib/declarative_policy/step.rb', line 81 def pass? @rule.pass?(@context) end |
#prevent? ⇒ Boolean
48 49 50 |
# File 'lib/declarative_policy/step.rb', line 48 def prevent? @action == :prevent end |
#repr ⇒ Object
85 86 87 |
# File 'lib/declarative_policy/step.rb', line 85 def repr "#{@action} when #{@rule.repr} (#{@context.repr})" end |
#score ⇒ Object
In the runner, steps are sorted dynamically by score, so that we are sure to compute them in close to the optimal order.
See also Rule#score, ManifestCondition#score, and Runner#steps_by_score.
29 30 31 32 33 34 35 36 37 38 |
# File 'lib/declarative_policy/step.rb', line 29 def score # we slightly prefer the preventative actions # since they are more likely to short-circuit case @action when :prevent @rule.score(@context) * (7.0 / 8) when :enable @rule.score(@context) end end |