strategize 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/strategize.rb +18 -5
- data/lib/strategize/exceptions.rb +5 -0
- data/lib/strategize/operations/operation.rb +33 -0
- data/lib/strategize/operations/operation_group.rb +45 -0
- data/lib/strategize/policies/policy.rb +47 -0
- data/lib/strategize/policies/policy_group.rb +43 -0
- data/lib/strategize/policies/policy_result.rb +33 -0
- data/lib/strategize/policies/policy_result_collection.rb +33 -0
- data/lib/strategize/rules/rule.rb +31 -0
- data/lib/strategize/rules/rule_group.rb +33 -0
- data/lib/strategize/rules/rule_result.rb +18 -0
- data/lib/strategize/rules/rule_result_collection.rb +45 -0
- data/test/test_helper.rb +7 -2
- metadata +30 -16
- data/lib/strategize/operation.rb +0 -18
- data/lib/strategize/policy.rb +0 -22
- data/lib/strategize/policy_group.rb +0 -28
- data/lib/strategize/rule.rb +0 -11
- data/lib/strategize/rule_group.rb +0 -16
- data/test/policy_group_test.rb +0 -21
- data/test/policy_test.rb +0 -13
- data/test/rule_test.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 42524de68454e2ad718b1849668425b46440fbac
|
4
|
+
data.tar.gz: 0191dd00cce17dbc790d18f14646ffa56a43dada
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6cf723d3e305c0f90fdce8cb878f51bd688477101f20bf82daa3b340e95de8c2146274a592860b6106492bfb1a9fcf9f3586ec27f856645a5d2135aa348e009d
|
7
|
+
data.tar.gz: ac6bd23200464784123842b3c84c7986f90cdfc96fa3b7e597a6ee17e50be42e4cb3b41fa37de51befb9acf2db48e88f3b3de2f46138441127e90fca2d6f1fb8
|
data/lib/strategize.rb
CHANGED
@@ -1,7 +1,20 @@
|
|
1
1
|
module Strategize
|
2
|
-
|
3
|
-
autoload :
|
4
|
-
autoload :
|
5
|
-
autoload :
|
6
|
-
autoload :
|
2
|
+
# Rules
|
3
|
+
autoload :Rule, 'strategize/rules/rule'
|
4
|
+
autoload :RuleGroup, 'strategize/rules/rule_group'
|
5
|
+
autoload :RuleResult, 'strategize/rules/rule_result'
|
6
|
+
autoload :RuleResultCollection, 'strategize/rules/rule_result_collection'
|
7
|
+
|
8
|
+
# Policies
|
9
|
+
autoload :Policy, 'strategize/policies/policy'
|
10
|
+
autoload :PolicyGroup, 'strategize/policies/policy_group'
|
11
|
+
autoload :PolicyResult, 'strategize/policies/policy_result'
|
12
|
+
autoload :PolicyResultCollection, 'strategize/policies/policy_result_collection'
|
13
|
+
|
14
|
+
# Operations
|
15
|
+
autoload :Operation, 'strategize/operations/operation'
|
16
|
+
autoload :OperationGroup, 'strategize/operations/operation_group'
|
17
|
+
|
18
|
+
# Exceptions
|
19
|
+
autoload :NotPolicyError, 'strategize/exceptions'
|
7
20
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Strategize
|
2
|
+
# Operations let you define a block of code that you would like to
|
3
|
+
# execute, and by calling process with a subject you can tell the
|
4
|
+
# operation what object you would like to execute the code against.
|
5
|
+
#
|
6
|
+
# Operations are similar to Rules, but the block of code that you
|
7
|
+
# pass in the constuctor does not have to be a predicate function.
|
8
|
+
class Operation
|
9
|
+
# @attr_reader name a descriptive name for the operation
|
10
|
+
attr_reader :name
|
11
|
+
|
12
|
+
# @attr_reader function A Proc or Lambda describing the code to be executed
|
13
|
+
attr_reader :function
|
14
|
+
|
15
|
+
# Create a new instance of Operation
|
16
|
+
#
|
17
|
+
# @param name [Symbol] a descriptive name for the operation
|
18
|
+
# @param function [Proc] the code to be executed
|
19
|
+
# @return [Operation]
|
20
|
+
def initialize(name, function)
|
21
|
+
@name = name
|
22
|
+
@function = function
|
23
|
+
end
|
24
|
+
|
25
|
+
# Execute the function against a specific object
|
26
|
+
#
|
27
|
+
# @param subject [Object] will become self when executing the function
|
28
|
+
# @return [void]
|
29
|
+
def process(subject)
|
30
|
+
subject.instance_exec(&@function)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Strategize
|
2
|
+
class OperationGroup
|
3
|
+
# @attr_reader operations [Array<Operation>]
|
4
|
+
attr_reader :operations
|
5
|
+
|
6
|
+
# Create a new instance of OperationGroup
|
7
|
+
#
|
8
|
+
# @param operations [Array<Operation>] the operations to be executed
|
9
|
+
def initialize(operations=[])
|
10
|
+
@operations = operations
|
11
|
+
end
|
12
|
+
|
13
|
+
# Add Operation to group
|
14
|
+
#
|
15
|
+
# @param name [Symbol] a descriptive name for the operation
|
16
|
+
# @param operation [Proc] a proc or lambda describing the code to be executed
|
17
|
+
def add(name, function)
|
18
|
+
operation = Operation.new(name, function)
|
19
|
+
@operations.push(operation)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Execute the code definined in each operation against a subject.
|
23
|
+
#
|
24
|
+
# @param subject [Object] a single object which acts as the subject for each operation
|
25
|
+
# @param subject [Hash] a hash of operation names and subjects
|
26
|
+
def run(subjects)
|
27
|
+
the_subjects = subjects
|
28
|
+
|
29
|
+
if !subjects.is_a?(Hash)
|
30
|
+
the_subjects = build_subjects_hash(subjects)
|
31
|
+
end
|
32
|
+
|
33
|
+
@operations.each do |operation|
|
34
|
+
subject = the_subjects[operation.name]
|
35
|
+
operation.process(subject) unless subject.nil?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def build_subjects_hash(subjects)
|
42
|
+
{ default: subjects }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Strategize
|
2
|
+
# The policy module allows you to define rules and an operation on
|
3
|
+
# any class that it is included on.
|
4
|
+
module Policy
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
base.send(:attr_reader, :object)
|
8
|
+
end
|
9
|
+
|
10
|
+
# These methods will be placed on the class that includes
|
11
|
+
# the Policy module.
|
12
|
+
module ClassMethods
|
13
|
+
# Get all the rules defined on this policy
|
14
|
+
#
|
15
|
+
# @return [RuleGroup]
|
16
|
+
def rules
|
17
|
+
@rules ||= RuleGroup.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# Get all the operations defined on this policy.
|
21
|
+
#
|
22
|
+
# @return [OperationGroup]
|
23
|
+
def operations
|
24
|
+
@operations ||= OperationGroup.new
|
25
|
+
end
|
26
|
+
|
27
|
+
# Define a rule for a policy
|
28
|
+
#
|
29
|
+
# @param name [Symbol] descriptive name for the rule
|
30
|
+
# @param predicate [Proc] code to execute
|
31
|
+
# @return [void]
|
32
|
+
def rule(name, predicate)
|
33
|
+
rules.add(name, predicate)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Define a block of code to run when you call the process
|
37
|
+
# method
|
38
|
+
#
|
39
|
+
# @param name [Symbol] the name of the context for the operation
|
40
|
+
# @param block [Proc] the code block to execute
|
41
|
+
# @return [void]
|
42
|
+
def operation(name = :default, &block)
|
43
|
+
operations.add(name, block)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Strategize
|
2
|
+
# The PolicyGroup allows you to evaluate a subject against
|
3
|
+
# multiple policies.
|
4
|
+
class PolicyGroup
|
5
|
+
attr_reader :policies
|
6
|
+
|
7
|
+
# Create a new PolicyGroup
|
8
|
+
def initialize
|
9
|
+
@policies = []
|
10
|
+
end
|
11
|
+
|
12
|
+
# Add policy to the group
|
13
|
+
#
|
14
|
+
# @param policy [Strategize::Policy] a class that includes the Policy module
|
15
|
+
# @return [void]
|
16
|
+
def add(policy)
|
17
|
+
fail Strategize::NotPolicyError unless policy?(policy)
|
18
|
+
@policies.push(policy)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Evaluate each policy against a given subject.
|
22
|
+
#
|
23
|
+
# @param subject [Object]
|
24
|
+
# @return [PolicyResultCollection]
|
25
|
+
def evaluate(subject)
|
26
|
+
results = @policies.map do |policy|
|
27
|
+
result_collection = policy.rules.evaluate(subject)
|
28
|
+
PolicyResult.new(policy, result_collection)
|
29
|
+
end
|
30
|
+
PolicyResultCollection.new(results, subject)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# Check if a policy includes the Policy module
|
36
|
+
#
|
37
|
+
# @private
|
38
|
+
# @param policy [Class] the class to check
|
39
|
+
def policy?(policy)
|
40
|
+
policy.included_modules.include?(Policy)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Strategize
|
2
|
+
# A PolicyResult is returned when you evaluate
|
3
|
+
# a PolicyGroup and allows you to view the
|
4
|
+
# RuleResultCollection and whether the policy
|
5
|
+
# was valid (all rules returned true)
|
6
|
+
class PolicyResult
|
7
|
+
attr_reader :policy, :rule_group, :subject
|
8
|
+
|
9
|
+
# Create a new PolicyEvaluation
|
10
|
+
#
|
11
|
+
# @param policy [Policy]
|
12
|
+
# @param rule_result_collection [RuleResultCollection]
|
13
|
+
# @return [PolicyResult]
|
14
|
+
def initialize(policy, rule_result_collection)
|
15
|
+
@policy = policy
|
16
|
+
@rule_result_collection = rule_result_collection
|
17
|
+
end
|
18
|
+
|
19
|
+
# Check if all the rules for the policy evaluated to true
|
20
|
+
#
|
21
|
+
# @return [Boolean]
|
22
|
+
def valid?
|
23
|
+
@rule_result_collection.all_valid?
|
24
|
+
end
|
25
|
+
|
26
|
+
# Get the results for rules on the policy
|
27
|
+
#
|
28
|
+
# @return [RuleResultCollection]
|
29
|
+
def rules
|
30
|
+
@rule_result_collection
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Strategize
|
2
|
+
# A wrapper for an array of PolicyResult instances.
|
3
|
+
class PolicyResultCollection
|
4
|
+
# @return [Array<PolicyResult>] the policy results for each policy
|
5
|
+
attr_reader :items
|
6
|
+
|
7
|
+
# @return [Object] the subject the policy was executed against
|
8
|
+
attr_reader :subject
|
9
|
+
|
10
|
+
# Create a new PolicyResultCollection
|
11
|
+
#
|
12
|
+
# @param policy_results [Array<PolicyResult]
|
13
|
+
# @param subject [Object] the subject the policies were executed against
|
14
|
+
def initialize(policy_results, subject)
|
15
|
+
@items = policy_results
|
16
|
+
@subject = subject
|
17
|
+
end
|
18
|
+
|
19
|
+
# Get an array of the PolicyResults that are valid, or return true
|
20
|
+
#
|
21
|
+
# @return [Array<PolicyResult>]
|
22
|
+
def passed
|
23
|
+
@items.select(&:valid)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Get an array of the PolicyResults that are invalid, or return false
|
27
|
+
#
|
28
|
+
# @return [Array<PolicyResult>]
|
29
|
+
def failed
|
30
|
+
@items.select { |rule| !rule.valid? }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Strategize
|
2
|
+
# The Rule class represents a predicate function that
|
3
|
+
# can be run against a specific subject.
|
4
|
+
#
|
5
|
+
# Define a new rule
|
6
|
+
# Rule.new :rule_name, -> { code to execute }
|
7
|
+
#
|
8
|
+
# Evaluate a rule
|
9
|
+
# rule = Rule.new :rule_name, -> { true }
|
10
|
+
# rule.evaluate(nil) #=> true
|
11
|
+
class Rule
|
12
|
+
attr_reader :name, :predicate
|
13
|
+
|
14
|
+
# Create a new rule
|
15
|
+
#
|
16
|
+
# @param name [Symbol] a descriptive name for the rule
|
17
|
+
# @param predicate [Proc] code block to be executed
|
18
|
+
def initialize(name, predicate)
|
19
|
+
@name = name
|
20
|
+
@predicate = predicate
|
21
|
+
end
|
22
|
+
|
23
|
+
# Execute the predicate against the subject
|
24
|
+
#
|
25
|
+
# @param subject [Object]
|
26
|
+
# @return [Boolean]
|
27
|
+
def evaluate(subject)
|
28
|
+
subject.instance_exec(&@predicate)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Strategize
|
2
|
+
# The RuleGroup allows you evaluate multiple rules against one subject.
|
3
|
+
class RuleGroup
|
4
|
+
attr_reader :rules
|
5
|
+
|
6
|
+
# Create new Rule Group
|
7
|
+
#
|
8
|
+
# @param rules [Array<Rule>] rules to be evaluated
|
9
|
+
def initialize(rules = [])
|
10
|
+
@rules = rules
|
11
|
+
end
|
12
|
+
|
13
|
+
# Add [Rule] to be evaluated
|
14
|
+
#
|
15
|
+
# @param name [Symbol] a descriptive name for the rule
|
16
|
+
# @param predicate [Lambda] a function that returns true or false
|
17
|
+
def add(name, predicate)
|
18
|
+
@rules.push(Rule.new(name, predicate))
|
19
|
+
end
|
20
|
+
|
21
|
+
# Evaluate all rules in group and return a collection
|
22
|
+
# of the results.
|
23
|
+
#
|
24
|
+
# @param subject [Object] object to evaluate rules against
|
25
|
+
# @return [RuleResultCollection] evaluation results
|
26
|
+
def evaluate(subject)
|
27
|
+
results = @rules.map do |rule|
|
28
|
+
RuleResult.new(rule, rule.evaluate(subject))
|
29
|
+
end
|
30
|
+
RuleResultCollection.new(results, subject)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Strategize
|
2
|
+
# A RuleResult represents the evaluation result, which gives
|
3
|
+
# you access to the Rule and whether it was valid or not.
|
4
|
+
class RuleResult
|
5
|
+
attr_reader :rule, :valid
|
6
|
+
|
7
|
+
# Create a new RuleResult which provides details on
|
8
|
+
# the evaluation of a rule.
|
9
|
+
#
|
10
|
+
# @param rule [Rule] the evaluated rule
|
11
|
+
# @param valid [Boolean] the result of the executed rule
|
12
|
+
# @return [RuleResult]
|
13
|
+
def initialize(rule, valid)
|
14
|
+
@rule = rule
|
15
|
+
@valid = valid
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Strategize
|
2
|
+
# Represents a collection of RuleResults, which lets you see
|
3
|
+
# what rules passed, failed, etc.
|
4
|
+
class RuleResultCollection
|
5
|
+
attr_reader :items, :subject
|
6
|
+
|
7
|
+
# Create a new RuleResultCollection
|
8
|
+
#
|
9
|
+
# @param rule_results [Array<RuleResult>]
|
10
|
+
# @param subject [Object]
|
11
|
+
# @return [RuleResultCollection]
|
12
|
+
def initialize(rule_results, subject)
|
13
|
+
@items = rule_results
|
14
|
+
@subject = subject
|
15
|
+
end
|
16
|
+
|
17
|
+
# Iterate over each [RuleResult] in the items Array.
|
18
|
+
#
|
19
|
+
# @param block [Proc]
|
20
|
+
def each(&block)
|
21
|
+
@items.each { |item| block.call(item) }
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns if all rules evaluated to true
|
25
|
+
#
|
26
|
+
# @return [Boolean]
|
27
|
+
def all_valid?
|
28
|
+
@items.all?(&:valid)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns all rules that evaluated to true
|
32
|
+
#
|
33
|
+
# @return [Array<RuleResult>]
|
34
|
+
def passed
|
35
|
+
@items.select(&:valid)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns all rules that evaluated to false
|
39
|
+
#
|
40
|
+
# @return [Array<RuleResult>]
|
41
|
+
def failed
|
42
|
+
@items.select { |rule| !rule.valid }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start do
|
3
|
+
add_filter '/test/'
|
4
|
+
add_group 'Rules', 'lib/strategize/rules'
|
5
|
+
add_group 'Policies', 'lib/strategize/policies'
|
6
|
+
end
|
7
|
+
|
1
8
|
require 'strategize'
|
2
9
|
|
3
10
|
require 'minitest/autorun'
|
@@ -6,6 +13,4 @@ require 'minitest/reporters'
|
|
6
13
|
test_root = File.dirname(__FILE__)
|
7
14
|
Dir["#{test_root}/support/*.rb"]. each { |file| require file }
|
8
15
|
|
9
|
-
|
10
|
-
|
11
16
|
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new(color: true)
|
metadata
CHANGED
@@ -1,27 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: strategize
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jdmorlan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest-reporters
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: simplecov
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
18
32
|
- !ruby/object:Gem::Version
|
19
33
|
version: '0'
|
20
34
|
type: :development
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
|
-
- - "
|
38
|
+
- - "~>"
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '0'
|
27
41
|
description: Strategize
|
@@ -31,16 +45,19 @@ extensions: []
|
|
31
45
|
extra_rdoc_files: []
|
32
46
|
files:
|
33
47
|
- lib/strategize.rb
|
34
|
-
- lib/strategize/
|
35
|
-
- lib/strategize/
|
36
|
-
- lib/strategize/
|
37
|
-
- lib/strategize/
|
38
|
-
- lib/strategize/
|
39
|
-
-
|
40
|
-
-
|
41
|
-
-
|
48
|
+
- lib/strategize/exceptions.rb
|
49
|
+
- lib/strategize/operations/operation.rb
|
50
|
+
- lib/strategize/operations/operation_group.rb
|
51
|
+
- lib/strategize/policies/policy.rb
|
52
|
+
- lib/strategize/policies/policy_group.rb
|
53
|
+
- lib/strategize/policies/policy_result.rb
|
54
|
+
- lib/strategize/policies/policy_result_collection.rb
|
55
|
+
- lib/strategize/rules/rule.rb
|
56
|
+
- lib/strategize/rules/rule_group.rb
|
57
|
+
- lib/strategize/rules/rule_result.rb
|
58
|
+
- lib/strategize/rules/rule_result_collection.rb
|
42
59
|
- test/test_helper.rb
|
43
|
-
homepage:
|
60
|
+
homepage: https://github.com/jdmorlan/strategize
|
44
61
|
licenses:
|
45
62
|
- MIT
|
46
63
|
metadata: {}
|
@@ -65,8 +82,5 @@ signing_key:
|
|
65
82
|
specification_version: 4
|
66
83
|
summary: Validate rules and perform operations
|
67
84
|
test_files:
|
68
|
-
- test/policy_group_test.rb
|
69
|
-
- test/policy_test.rb
|
70
|
-
- test/rule_test.rb
|
71
85
|
- test/test_helper.rb
|
72
86
|
has_rdoc:
|
data/lib/strategize/operation.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
module Strategize
|
2
|
-
module Operation
|
3
|
-
def self.included(base)
|
4
|
-
base.extend(ClassMethods)
|
5
|
-
base.send(:attr_reader, :object)
|
6
|
-
end
|
7
|
-
|
8
|
-
module ClassMethods
|
9
|
-
def operation(&block)
|
10
|
-
@operation = block
|
11
|
-
end
|
12
|
-
|
13
|
-
def process(subject)
|
14
|
-
subject.instance_exec &@operation
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/lib/strategize/policy.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
module Strategize
|
2
|
-
module Policy
|
3
|
-
def self.included(base)
|
4
|
-
base.extend(ClassMethods)
|
5
|
-
base.send(:attr_reader, :object)
|
6
|
-
end
|
7
|
-
|
8
|
-
module ClassMethods
|
9
|
-
def rules
|
10
|
-
@rules ||= RuleGroup.new
|
11
|
-
end
|
12
|
-
|
13
|
-
def rule(predicate)
|
14
|
-
rules.add(predicate)
|
15
|
-
end
|
16
|
-
|
17
|
-
def evaluate(subject)
|
18
|
-
rules.evaluate(subject)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
module Strategize
|
2
|
-
class PolicyGroup
|
3
|
-
NotPolicyError = Class.new(RuntimeError)
|
4
|
-
|
5
|
-
def initialize
|
6
|
-
@policies = []
|
7
|
-
end
|
8
|
-
|
9
|
-
def add(policy)
|
10
|
-
raise NotPolicyError unless is_policy(policy)
|
11
|
-
@policies.push(policy)
|
12
|
-
end
|
13
|
-
|
14
|
-
def select(subject)
|
15
|
-
@policies.select { |p| p.evaluate(subject) }
|
16
|
-
end
|
17
|
-
|
18
|
-
def find(subject)
|
19
|
-
self.select(subject).first
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def is_policy(policy)
|
25
|
-
policy.included_modules.include?(Policy)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
data/lib/strategize/rule.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
module Strategize
|
2
|
-
class RuleGroup
|
3
|
-
def initialize
|
4
|
-
@rules = []
|
5
|
-
end
|
6
|
-
|
7
|
-
def add(predicate)
|
8
|
-
predicate = Rule.new(predicate) if predicate.is_a?(Proc)
|
9
|
-
@rules.push(predicate)
|
10
|
-
end
|
11
|
-
|
12
|
-
def evaluate(subject)
|
13
|
-
@rules.all? { |r| r.evaluate(subject) }
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
data/test/policy_group_test.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class PolicyGroupTest < Minitest::Test
|
4
|
-
def setup
|
5
|
-
@group = Strategize::PolicyGroup.new
|
6
|
-
@group.add(CanDrinkPolicy)
|
7
|
-
@group.add(CanSmokePolicy)
|
8
|
-
@group.add(CanVotePolicy)
|
9
|
-
end
|
10
|
-
|
11
|
-
def test_collection_operations_work
|
12
|
-
subject = OpenStruct.new(age: 19)
|
13
|
-
data = OpenStruct.new(permissions: {})
|
14
|
-
|
15
|
-
policies = @group.select(subject)
|
16
|
-
policies.each { |p| p.process(data) }
|
17
|
-
|
18
|
-
assert_equal true, data.permissions[:can_vote]
|
19
|
-
assert_equal true, data.permissions[:can_smoke]
|
20
|
-
end
|
21
|
-
end
|
data/test/policy_test.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class PolicyTest < Minitest::Test
|
4
|
-
def test_can_drink_is_valid
|
5
|
-
subject = OpenStruct.new(age: 22)
|
6
|
-
CanDrinkPolicy.evaluate(subject)
|
7
|
-
end
|
8
|
-
|
9
|
-
def test_cannot_drink
|
10
|
-
subject = OpenStruct.new(age: 20)
|
11
|
-
CanDrinkPolicy.evaluate(subject)
|
12
|
-
end
|
13
|
-
end
|
data/test/rule_test.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class RuleTest < Minitest::Test
|
4
|
-
def test_can_create_rule
|
5
|
-
rule = Strategize::Rule.new(-> { true })
|
6
|
-
assert rule.is_a?(Strategize::Rule)
|
7
|
-
end
|
8
|
-
|
9
|
-
def test_rule_is_valid
|
10
|
-
rule = Strategize::Rule.new(-> { true })
|
11
|
-
assert rule.evaluate(nil)
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_rule_is_not_valid
|
15
|
-
rule = Strategize::Rule.new(-> { false })
|
16
|
-
refute rule.evaluate(nil)
|
17
|
-
end
|
18
|
-
end
|