Class: Torm::RulesEngine
- Inherits:
-
Object
- Object
- Torm::RulesEngine
- Defined in:
- lib/torm/rules_engine.rb
Defined Under Namespace
Classes: RuleVariationHelper
Constant Summary collapse
- DEFAULT_POLICIES =
Policies (priorities) in order of important -> least important.
[:law, :coc, :experiment, :default].freeze
Instance Attribute Summary collapse
-
#conditions_whitelist ⇒ Object
readonly
Returns the value of attribute conditions_whitelist.
-
#dirty ⇒ Object
Returns the value of attribute dirty.
-
#policies ⇒ Object
Returns the value of attribute policies.
-
#rules ⇒ Object
readonly
Returns the value of attribute rules.
-
#rules_file ⇒ Object
Returns the value of attribute rules_file.
Class Method Summary collapse
-
.from_json(json) ⇒ Object
Load an engine from JSON.
-
.load(rules_file: Torm.default_rules_file) ⇒ Torm::RulesEngine
Load rules from a file and create a new engine for it.
Instance Method Summary collapse
-
#add_rule(name, value, policy, conditions = {}) ⇒ Torm::RulesEngine
Add a new rule.
-
#add_rules(name, value, policy) {|Torm::RulesEngine::RuleVariationHelper| ... } ⇒ Torm::RulesEngine
Add multiple rules via the block syntax:.
-
#as_hash ⇒ Hash
Return a hash with all rules and policies, useful for serialisation.
-
#decide(name, environment = {}) ⇒ Object
Evaluate a rule and return its result.
-
#dirty? ⇒ true, false
Have any rules been added since the last save or load?.
-
#initialize(rules: {}, dirty: false, policies: DEFAULT_POLICIES.dup, rules_file: Torm.default_rules_file) ⇒ RulesEngine
constructor
A new instance of RulesEngine.
-
#save ⇒ Object
Save the current rules to the file.
-
#to_json ⇒ String
Serialise the data from
as_hash
.
Constructor Details
#initialize(rules: {}, dirty: false, policies: DEFAULT_POLICIES.dup, rules_file: Torm.default_rules_file) ⇒ RulesEngine
Returns a new instance of RulesEngine.
10 11 12 13 14 15 16 |
# File 'lib/torm/rules_engine.rb', line 10 def initialize(rules: {}, dirty: false, policies: DEFAULT_POLICIES.dup, rules_file: Torm.default_rules_file) @rules = rules @dirty = dirty @policies = policies @rules_file = rules_file @conditions_whitelist = {} end |
Instance Attribute Details
#conditions_whitelist ⇒ Object (readonly)
Returns the value of attribute conditions_whitelist.
6 7 8 |
# File 'lib/torm/rules_engine.rb', line 6 def conditions_whitelist @conditions_whitelist end |
#dirty ⇒ Object
Returns the value of attribute dirty.
8 9 10 |
# File 'lib/torm/rules_engine.rb', line 8 def dirty @dirty end |
#policies ⇒ Object
Returns the value of attribute policies.
7 8 9 |
# File 'lib/torm/rules_engine.rb', line 7 def policies @policies end |
#rules ⇒ Object (readonly)
Returns the value of attribute rules.
6 7 8 |
# File 'lib/torm/rules_engine.rb', line 6 def rules @rules end |
#rules_file ⇒ Object
Returns the value of attribute rules_file.
8 9 10 |
# File 'lib/torm/rules_engine.rb', line 8 def rules_file @rules_file end |
Class Method Details
.from_json(json) ⇒ Object
Load an engine from JSON. This means we can export rules engines across systems: store rules in 1 place, run them ‘everywhere’ at native speed. Due to the high number of symbols we use, we have to convert the JSON string data for each rule on import. Good thing: we should only have to do this once on boot.
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/torm/rules_engine.rb', line 126 def self.from_json(json) dump = MultiJson.load(json) data = { policies: dump['policies'].map(&:to_sym), } engine = new(**data) dump['rules'].each do |name, rules| rules.each do |rule| value = rule['value'] value = Torm.symbolize_keys(value) if Hash === value policy = rule['policy'].to_sym conditions = Torm.symbolize_keys(rule['conditions']) engine.add_rule(name, value, policy, conditions) end end engine.dirty = false engine end |
.load(rules_file: Torm.default_rules_file) ⇒ Torm::RulesEngine
Load rules from a file and create a new engine for it. Note: this does not replace the Torm::RulesEngine.instance, you have to do this yourself if required.
149 150 151 152 153 154 155 156 157 158 |
# File 'lib/torm/rules_engine.rb', line 149 def self.load(rules_file: Torm.default_rules_file) if File.exist?(rules_file) json = File.read(rules_file) engine = self.from_json(json) engine.rules_file = rules_file engine else nil end end |
Instance Method Details
#add_rule(name, value, policy, conditions = {}) ⇒ Torm::RulesEngine
Add a new rule. Will mark the engine as dirty when a rules was added.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/torm/rules_engine.rb', line 33 def add_rule(name, value, policy, conditions={}) raise "Illegal policy: #{policy.inspect}, must be one of: #{policies.inspect}" unless policies.include?(policy) rules_array = rules_for(name) value = { minimum: value.min, maximum: value.max } if Range === value new_rule = { value: value.freeze, policy: policy, conditions: conditions.freeze }.freeze unless rules_array.include?(new_rule) rules_array << new_rule # Sort rules so that the highest policy level is sorted first and then the most complex rule before the more general ones rules_array.sort_by! { |rule| [policies.index(rule[:policy]), -rule[:conditions].size] } conditions_whitelist_for(name).merge conditions.keys @dirty = true end self end |
#add_rules(name, value, policy) {|Torm::RulesEngine::RuleVariationHelper| ... } ⇒ Torm::RulesEngine
Add multiple rules via the block syntax:
85 86 87 88 89 90 91 92 93 |
# File 'lib/torm/rules_engine.rb', line 85 def add_rules(name, value, policy) # Add the default rule add_rule(name, value, policy) rule_variation = RuleVariationHelper.new(self, name) yield rule_variation if block_given? self end |
#as_hash ⇒ Hash
Return a hash with all rules and policies, useful for serialisation.
109 110 111 112 113 114 |
# File 'lib/torm/rules_engine.rb', line 109 def as_hash { policies: policies, rules: rules } end |
#decide(name, environment = {}) ⇒ Object
Evaluate a rule and return its result. Depending on the rule, different values are returned.
98 99 100 101 102 103 104 |
# File 'lib/torm/rules_engine.rb', line 98 def decide(name, environment={}) raise "Unknown rule: #{name.inspect}" unless rules.has_key?(name) environment = Torm.symbolize_keys(environment) decision_environment = Torm.slice(environment, *conditions_whitelist_for(name)) answer = make_decision(name, decision_environment) answer end |
#dirty? ⇒ true, false
Have any rules been added since the last save or load?
20 21 22 |
# File 'lib/torm/rules_engine.rb', line 20 def dirty? @dirty end |
#save ⇒ Object
Save the current rules to the file.
161 162 163 164 165 |
# File 'lib/torm/rules_engine.rb', line 161 def save Torm.atomic_save(rules_file, to_json + "\n") @dirty = false nil end |
#to_json ⇒ String
Serialise the data from as_hash
.
119 120 121 |
# File 'lib/torm/rules_engine.rb', line 119 def to_json MultiJson.dump(as_hash) end |