在Ruby中指定和执行规则

时间:2011-08-26 17:21:33

标签: ruby-on-rails parsing event-handling rule-engine

我正在寻找一个可以帮助我完成以下任务的Ruby / Rails工具:

我想在我的数据库中存储以下字符串以及类似的字符串。当一个对象被创建,更新,删除等时,我想要遍历所有字符串,检查CRUD事件是否与字符串的条件匹配,如果是,则运行指定的动作。

When a new ticket is created and it's category=6 then notify user 1234 via email

我打算创建一个构建这些字符串的接口,因此它不需要是一个人类可读的字符串。如果JSONish结构更好,或者工具有现有语言,那就太棒了。我有点想法:

{
  object_types: ['ticket'],
  events: ['created', 'updated'],
  conditions:'ticket.category=6',
  actions: 'notify user',
  parameters: {
    user:1234,
    type:'email'
  }
}

基本上,我需要以下内容:

  1. 监控CRUD事件 - 如果该工具有办法做到这一点会很好,但是如果工具本身没有提供它,我可以在这里使用Rails的ModelObservers

  2. 查找所有匹配的“规则” - 这是我的主要未知数...

  3. 执行请求的方法/参数 - 理想情况下,这将在我的Ruby代码中定义为类/方法

  4. 我是否应该调查任何现有工具?

    修改

    感谢你们到目前为止的回复!我真的很感谢你把我指向正确的道路。

    这里的用例是我们有许多不同的客户,有许多不同的业务规则。对于适用于所有客户端的规则,我可以轻松地在代码中创建它们(使用像Ruleby这样的东西),但是对于所有特定于客户端的规则,我想将它们存储在数据库中。理想情况下,规则可以写入一次,存储在代码中或数据库中,然后运行(使用Resque来提高性能)。

    在这一点上,看起来我将不得不自己动手,所以对于最好的方法,或者我应该调查的任何工具的任何想法都将非常感激。

    再次感谢!

3 个答案:

答案 0 :(得分:7)

我认为自己写一些东西并不是一件很重要的事情,我不知道有什么宝石可以做到这一点(但如果有人写了一个就好了!)

我会用以下方式处理项目,我想的方式是你不想在用户保存的时候进行规则匹配,因为它可能需要一段时间并且可能会中断用户体验和/或者减慢服务器的速度,所以......

  1. 每次CRUD事件发生时,使用观察者存储记录,或者使用Acts as Audited gem更简单地使用观察者为您执行此操作。
  2. 1.5。使用rake任务,从crontab运行以运行最新的更改,可能每分钟,或者您可以使用Resque来处理大量工作

    1. 创建一组表,用于定义用户可以选择的可能规则,可能类似
    2. 表:规则

      名称

      ForEvent(例如CRUD)

      TableInQuestion

      • FieldOneName

      • FieldOneCondition等。

      MethodToExecute

      您可以使用一些元编程来执行您的方法,因为您的方法知道您的表名和记录ID,所以可以选择这个。

      附加说明

      解决这个问题的最佳方法是从简单开始,然后向上工作。为了让简单版本先工作,我会做以下事情......

      1. 安装作为审核
      2. 在创建的审核表中添加一个附加字段:when_processed
      3. 在/ lib文件夹中创建一个名为processrules的模块,大致就是这个

        3.1获取所有未处理的审核条目 3.2将它们标记为已处理(此时可能会制作另一个小型审计表以记录发生的事件)

      4. 现在创建一个只有名称和条件声明的规则表,或许可以添加一些示例表来继续

        姓名:首先|规则声明:'SELECT 1 WHERE table.value = something'

      5. 调整您的新processrules方法,为每个更改的条目执行该sql(可能您希望将其限制为您正在使用的表)

      6. 如果规则匹配,请将其添加到您的日志文件中。

      7. 从这里你可以推断出你需要的其他功能,或者可能会问另一个关于动态调用方法的元编程方面的问题,因为这个问题非常广泛,我非常乐意为你提供进一步的帮助。

        我倾向于认为进行任务处理的最佳方法是首先很好地设置流程,以便它可以在任何服务器负载和情况下工作,然后插入自定义位。

答案 1 :(得分:3)

你可以使这个抽象得足以让你可以指定任意条件和规则,但是你要开发一个框架/引擎而不是解决你的应用程序的特定问题。

使用ActiveRecord::Observer很有可能解决您的需求,因为您可以对所需的所有不同类型的条件进行硬编码,然后只将未知数放入数据库中。例如,假设您知道有人在观看类别,然后创建像category_watchers这样的关联,并使用以下观察者:

class TicketObserver < ActiveRecord::Observer
  # observe :ticket # not needed here, since it's inferred by the class name

  def after_create(ticket)
    ticket.category.watchers.each{ |user| notify_user(ticket, user) }
  end

  # def after_update ... (similar)

  private

  def notify_user(ticket, user)
    # lookup the user's stored email preferences
    # send an email if appropriate
  end
end

如果您要存储电子邮件首选项以及用户正在观看该类别的事实,请使用带有标记的连接模型。

如果你想进一步抽象它,我建议使用treetop之类的东西来自己生成观察者,但我不相信这比在代码中抽象类似的观察者更有价值。

答案 2 :(得分:2)

Ruby & Rules Engines SO post可能包含一些您可能会觉得有用的信息。还有另一个基于Ruby的规则引擎,您可能也想要探索它 - Ruleby

希望这有助于您开始调查。