strategize 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|