Class: Torm::RulesEngine
- Inherits:
-
Object
- Object
- Torm::RulesEngine
- Defined in:
- lib/torm/rules_engine.rb
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
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.
-
#verbose ⇒ Object
Returns the value of attribute verbose.
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.
-
.rules_file ⇒ Object
Where we store the rules file.
Instance Method Summary collapse
-
#add_rule(name, value, policy, conditions = {}) ⇒ Torm::RulesEngine
Add a new rule.
- #as_hash ⇒ Object
- #decide(name, environment = {}) ⇒ Object
-
#dirty? ⇒ Boolean
Have any rules been added since the last save or load?.
-
#initialize(rules: {}, conditions_whitelist: {}, dirty: false, policies: DEFAULT_POLICIES.dup, verbose: false) ⇒ RulesEngine
constructor
A new instance of RulesEngine.
-
#save(rules_file: self.class.rules_file) ⇒ Object
Save the current rules to a file.
- #to_json ⇒ Object
Constructor Details
#initialize(rules: {}, conditions_whitelist: {}, dirty: false, policies: DEFAULT_POLICIES.dup, verbose: false) ⇒ 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: {}, conditions_whitelist: {}, dirty: false, policies: DEFAULT_POLICIES.dup, verbose: false) @rules = rules @conditions_whitelist = conditions_whitelist @dirty = dirty @policies = policies @verbose = verbose end |
Instance Attribute Details
#conditions_whitelist ⇒ Object
Returns the value of attribute conditions_whitelist.
7 8 9 |
# File 'lib/torm/rules_engine.rb', line 7 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 |
#verbose ⇒ Object
Returns the value of attribute verbose.
7 8 9 |
# File 'lib/torm/rules_engine.rb', line 7 def verbose @verbose 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.
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/torm/rules_engine.rb', line 64 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.
92 93 94 95 96 97 98 99 |
# File 'lib/torm/rules_engine.rb', line 92 def self.load(rules_file: Torm.default_rules_file) if File.exist?(rules_file) json = File.read(rules_file) self.from_json(json) else nil end end |
.rules_file ⇒ Object
Where we store the rules file.
84 85 86 |
# File 'lib/torm/rules_engine.rb', line 84 def self.rules_file Rails.root.join('tmp', 'rules.json').to_s 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.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/torm/rules_engine.rb', line 26 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 |
#as_hash ⇒ Object
50 51 52 53 54 55 |
# File 'lib/torm/rules_engine.rb', line 50 def as_hash { policies: policies, rules: rules } end |
#decide(name, environment = {}) ⇒ Object
41 42 43 44 45 46 47 48 |
# File 'lib/torm/rules_engine.rb', line 41 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) #Rails.logger.debug "DECISION: #{answer.inspect} (#{name.inspect} -> #{environment.inspect})" answer end |
#dirty? ⇒ Boolean
Have any rules been added since the last save or load?
19 20 21 |
# File 'lib/torm/rules_engine.rb', line 19 def dirty? @dirty end |
#save(rules_file: self.class.rules_file) ⇒ Object
Save the current rules to a file.
102 103 104 105 106 |
# File 'lib/torm/rules_engine.rb', line 102 def save(rules_file: self.class.rules_file) Torm.atomic_save(rules_file, to_json + "\n") @dirty = false nil end |
#to_json ⇒ Object
57 58 59 |
# File 'lib/torm/rules_engine.rb', line 57 def to_json MultiJson.dump(as_hash) end |