Class: Animal::Rule

Inherits:
Object
  • Object
show all
Defined in:
lib/animal/rule.rb

Overview

The basis for the rules engine used for classifying nodes

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(statement, when_true, when_false = {}) ⇒ Rule

Returns a new instance of Rule.



33
34
35
36
37
# File 'lib/animal/rule.rb', line 33

def initialize(statement, when_true, when_false = {})
  @statement  = statement
  @when_true  = when_true
  @when_false = when_false
end

Instance Attribute Details

#when_falseObject (readonly)

Returns the value of attribute when_false.



9
10
11
# File 'lib/animal/rule.rb', line 9

def when_false
  @when_false
end

#when_trueObject (readonly)

Returns the value of attribute when_true.



9
10
11
# File 'lib/animal/rule.rb', line 9

def when_true
  @when_true
end

Class Method Details

.allObject



11
12
13
14
15
16
17
18
19
20
21
# File 'lib/animal/rule.rb', line 11

def self.all
  rules = []
  Animal::Plugins::Storage::Yaml.all('rules').each do |data|
    rules << if data.key?(:failure)
               Rule.new(data[:statement], data[:success], data[:failure])
             else
               Rule.new(data[:statement], data[:success])
             end
  end
  rules
end

.apply_all_for(node) ⇒ Object



23
24
25
26
27
28
29
30
31
# File 'lib/animal/rule.rb', line 23

def self.apply_all_for(node)
  operations = { add: [], subtract: [] }
  all.each do |rule|
    result = rule.apply_for(node)
    operations[:add].concat result[:add] if result.key?(:add)
    operations[:subtract].concat result[:subtract] if result.key?(:subtract)
  end
  operations[:add].uniq - operations[:subtract]
end

Instance Method Details

#apply_for(node) ⇒ Object



84
85
86
87
88
89
90
# File 'lib/animal/rule.rb', line 84

def apply_for(node)
  evaluate(node, parse) ? @when_true : @when_false
rescue => e
  # TODO: output something for debugging here since evaluate failed to run
  STDERR.puts "Exception occurred on Rule#apply_for(#{node}) for `#{@statement}`: #{e.message}"
  {}
end

#evaluate(node, condition) ⇒ Object

Used to evaluate the conditions provided by parsing a rule statement rubocop:disable Metrics/AbcSize



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/animal/rule.rb', line 47

def evaluate(node, condition)
  plugin = get_plugin_class(condition[:plugin]) if condition.key?(:plugin)
  if [:and, :or].include?(condition[:conjunction])
    recurse_on_conjunction(node, condition[:conditions], condition[:conjunction])
  elsif condition[:operator] == :like
    # Use the plugin to lookup a key and match it against the condition's value
    plugin.get(node, condition[:key]).match(sanitize_regexp(condition[:value])) ? true : false
  elsif condition[:operator] == '='.to_sym
    plugin.get(node, condition[:key]) == condition[:value]
  elsif ['!=', '>=', '<=', '>', '<'].include?(condition[:operator].to_s)
    plugin.get(node, condition[:key]).send(condition[:operator], condition[:value])
  else
    false
  end
end

#parseObject



39
40
41
42
43
# File 'lib/animal/rule.rb', line 39

def parse
  parser = RulesParser.new
  result = parser.parse(@statement)
  result.conditions
end

#recurse_on_conjunction(node, conditions, conjunction) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/animal/rule.rb', line 63

def recurse_on_conjunction(node, conditions, conjunction)
  subresult = nil
  if conjunction == :and
    conditions.each do |subcondition|
      subresult = evaluate(node, subcondition)
      break if subresult.is_a? FalseClass
    end
  elsif conjunction == :or
    subresult = nil
    conditions.each do |subcondition|
      subresult = evaluate(node, subcondition)
      break if subresult.is_a? TrueClass
    end
  end
  subresult ? true : false
end

#sanitize_regexp(value) ⇒ Object



80
81
82
# File 'lib/animal/rule.rb', line 80

def sanitize_regexp(value)
  value.gsub(%r{(^/|/$)}, '')
end