rein - Rule Engine IN ruby

What's rein?

rein is simple rule engine in Ruby. rein enables to control applications that are filtering mails or validating data, etc. with rules.

Usage

Write rules in rule file and start rule engine with calling RuleEngine#fire(). The method receives an object to apply the rules.

require 'rein'
engine = Rein::RuleEngine.new "rules.yaml"
engine.fire obj

Rule file

Rule file is a YAML file. Write rules for rules at top level. Each rule requires name, condition, action.

An example of rule file is the following:

rules:
  -
    name:      MailingList
    condition: from = "mlname@xxx.com"
    action:    move "MailBox"

  -
    name:      DearFriends
    condition: (from = "john@xxx.net") or (from = "paul@xxx.net")
    action:    move "DearFriends"

Rule

Rule has "condition" and "action". When an object is matched the condition, the action is processed for the object.

Condition

Format of condition is "LHS(left hand side), operator, RHS(right hand side)". Write "and/or" to join conditions, "not" before a condition to deny. When you use the boolean operators, enclose a condition with parentheses. An example of condition is the following:

name =¡ÆMyName¡Ç
register_date > '2000/1/1¡Ç
(title =~ /R*/) and (name =~ /O*/)
not (time < 20)

String without quotation marks like "name" or "register_date" is a message for object to evaluate. The above conditions is parsed as ruby code the following:

object.name == 'MyName'
object.register_date > '2000/1/1'
(object.title =~ /R*/) and (object.name =~ /O*/)
not (object.time < 20)

Operators

Operators "=, !=, >, <, >=, <=, =~" are ready by default. To define a new operator, specify "operator string, method name (to evaluate the operator), object" with Qualifier.set_operator().

For example, we define "start" operator to evaluate whether LHS object starts with RHS string. First, define StartOperatorSupport class and start() method to evaluate the operator.

class StartOperatorSupport
  def self.start( left, right )
    left =~ /\A#{right}/
  end
end

Next, set the operator with method name and class (or an object) evaluate.

Qualifier.set_operator('start', :start, StartOperatorSupport)

Action

When an object is matched the condition, the action is processed for the object. You can specify an action or actions.

In now implementation, action is parsed with instance_eval() as Ruby code.

Conflict Resolution Strategies

If some rules match an object, rule engine applies one of the rules. In now version, you can set priority for rules to resolve conflict.

You can set priority between 0 and 1 for each rules. When rules conflict, rule engine applies a rule with highest priority. If highest priorities are, the engine applies a rule defined fastest in rule file.