红宝石规则引擎

时间:2012-08-28 15:11:07

标签: ruby-on-rails ruby dsl

我觉得我要在这里重新发明轮子,所以在我做之前......

我需要处理大量数据,处理数据的“规则”会随着时间的推移而发展,所以我认为实现一个简单的规则引擎是有序的。

注意我不是在寻找自然语言解析器,我希望所有规则都是ruby procs。

我可以想象语法看起来像:

engine = SimpleRulesEngine.new

rule = engine.add_rule(priority: 10) do |row|
  row.name != 'George'
end

rule.action do |row|
  puts "Yikes, name is not George!, it was #{row.name}"
  row.update_attribute :name, 'George'
end

engine.process collection

我想知道是否有任何现有的图案或宝石可以帮助解决这个问题。看起来最接近的是ruleby,但似乎没有积极维护,对我的问题来说似乎太复杂了。

谢谢!


请注意,这是一个类似的问题:Ruby & Rules Engines,但不同之处在于,我不关心自然语言处理和规则存储。

5 个答案:

答案 0 :(得分:6)

@DaveNewton对我说了几句话,显然基本上我正在为我的应用寻找一些简单的DSL,这就是我最终使用的 - 它非常简单,但是它对其他人有用:

# /lib/simple_rules_engine
# To use, just include it in any file where you need some rules engine love ...
# then defile rules like so:
#
# rule :name_of_rule,
#       priority: 10,
#       validate: lambda {|o| # do something with o}
#       fail: lambda {|o| o.fail!}} 
# 
# then to run the engine
# process_rules(your_data_set)
#   
module SimpleRulesEngine
  extend ActiveSupport::Concern

  included do
    class_attribute :rules
    self.rules = []
  end

  module ClassMethods

    # rule :name_of_rule,
    #       priority: 10,
    #       validate: lambda {|o| # do something with o}
    #       fail: lambda {|o| o.fail!}}
    def rule(name,options={})
      self.rules << SimpleRulesEngine::Rule.new(name,options)
    end

    def process_rules(collection)
      collection.each do |row|
        rules.sort_by(&:priority).each do |rule|
          rule.run(row)
        end
        row.valid!
      end
    end

  end

  ## Helper Classes

  class Rule

    attr_accessor :priority
    attr_accessor :name

    # proc to test
    attr_accessor :validate

    # if valid
    attr_accessor :success


    # if invalid
    attr_accessor :fail

    NO_OP = lambda {|o| true }

    def initialize(name, options={})
      self.name = name
      self.priority = options[:priority] || 10
      self.validate = options[:validate] || NO_OP
      self.fail = options[:fail] || NO_OP
      self.success = options[:success] || NO_OP
    end

    def run(data)

      if validate.call(data)
        success.call(data)
      else
        fail.call(data)
      end

    end
  end

end

答案 1 :(得分:1)

与其他现有的Ruby规则引擎相比,Ruleby似乎是最积极维护的:

然而, Wongi Engine 看起来很有希望,可能会成为您所需要的。

答案 2 :(得分:1)

或许看看Wongi,正如Stratus3D建议的那样。从第一眼看它看起来不错,并有一个很好的介绍。我将在接下来的几周内在一个更复杂的测试用例上测试它。

另一方面,Rools似乎没有维护(rubyforge页面已经死了,我发现的所有叉子似乎也已经死了)。

答案 3 :(得分:0)

我一直在和Ruleby一起玩几个星期并且使用起来并不太复杂,虽然我添加的复杂功能是使用大量的case语句以编程方式将规则加载到引擎中。

一旦你理解了事实之类的东西在发动机和发动机中是持久的。每次后续运行不只是评估你刚才提出的事实,而是你先前所说的事实,这是非常直接的。虽然当我遇到运行时错误时很难解决问题(因为我目前正在使用其中一部分),但并不喜欢blackbox如何使用blackbox。

答案 4 :(得分:0)

不要忘记wongi-engine gem(https://github.com/ulfurinn/wongi-engine)。它基于Rete算法(http://en.wikipedia.org/wiki/Rete_algorithm/),其语法类似于您要查找的内容。