EvoBal/app/services/rules_evaluator.rb

105 lines
2.5 KiB
Ruby

class RulesEvaluator
def evaluate(email)
RuleSet.enabled.each do |rule_set|
if evaluate_rule_set(email, rule_set)
rule_set.actions.enabled.each do |action|
klass = action.class_name.constantize
email = klass.new.process(email)
# rescue NameError => ex
# # TODO: log a warning
end
end
end
email
end
def evaluate_rule_set(email, rule_set)
rules_state = true
rule_set.rules.enabled.each do |rule|
subjects = prepare_subjects(email, rule)
result = apply_rule(subjects, rule)
result = ! result if rule.inverted?
rules_state = apply_operator(rules_state, rule_set.operator, result)
break unless rules_state
end
rules_state
end
private
def prepare_subjects(email, rule)
case rule.subject_type.downcase
when "header"
Array(email.header_values(rule.subject_value))
when "body"
Array(email.plain_body)
else
raise ArgumentError, "Unrecognized subject type '#{rule.subject_type}'"
end
end
def apply_rule(subjects, rule)
case rule.condition_type.downcase
when "match", "matches"
subjects.any? { |subject|
pattern = Regexp.new(rule.condition_value)
subject.match?
}
when "equal", "equals"
subjects.any? { |subject|
subject == rule.condition_value
}
when "start", "starts"
subjects.any? { |subject|
subject.starts_with? rule.condition_value
}
when "end", "ends"
subjects.any? { |subject|
subject.ends_with? rule.condition_value
}
when "contain", "contains"
subjects.any? { |subject|
subject.include? rule.condition_value
}
when "exist", "exists"
subjects.any? { |subject|
subject.exists?
}
when "empty"
subjects.all? { |subject|
subject.empty?
}
when "date_before"
# subjects.all? { |subject|
# subject.empty?
# }
when "date_after"
# subjects.all? { |subject|
# subject.empty?
# }
else
true
end
def apply_operator(state, operator, result)
case operator.upcase
when "AND"
(state and result)
when "OR"
(state or result)
when "XOR"
(state or result) and not (rules_state and result)
else
raise ArgumentError, "Unrecognized logic '#{rule_set.operator}'"
end
end
end
end