【问题标题】:Specifying and Executing Rules in Ruby在 Ruby 中指定和执行规则
【发布时间】:2011-08-26 17:21:33
【问题描述】:

我正在寻找可以帮助我完成以下任务的 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 代码中定义为类/方法

是否有任何我应该研究的现有工具?

编辑:

感谢大家到目前为止的回复!非常感谢您为我指明正确的道路。

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

在这一点上,我似乎不得不自己动手了,所以任何关于最好的方法的想法,或者我应该研究的任何工具,都将不胜感激。

再次感谢!

【问题讨论】:

  • 你可以使用像after_createafter_update这样的回调吗?
  • @mischa - 在某种程度上,是的。其中每一个都应该触发一个事件,然后其他东西应该处理该事件以寻找匹配的规则,如果找到任何匹配规则,则对这些规则执行操作。很好地抽象它,这样我就不必手动触发事件并进行规则匹配会很好:-)

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


【解决方案1】:

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

我将通过以下方式处理该项目,我的想法是您不想在用户保存时进行规则匹配,因为这可能需要一段时间并且可能会中断用户体验和/或者让服务器变慢,所以...

  1. 每次发生 CRUD 事件时,使用观察者来存储记录,或者使用 Acts as Audited gem 为您做这件事让事情变得更简单。

1.5。使用 rake 任务,从您的 crontab 运行以运行最新的更改,可能每分钟一次,或者您可以使用 Resque,它可以很好地处理大量作业

  1. 创建一组表,这些表定义了用户可以从中选择的可能规则,可能类似于

表格:规则

名字

ForEvent(例如 CRUD)

问题表

  • FieldOneName

  • FieldOneCondition 等

方法执行

您可以使用一些元编程来执行您的方法,并且由于您的方法知道您的表名和记录 ID,因此可以获取它。

附加说明

最好的方法是从简单开始,然后向上工作。为了让简单版本首先工作,我会执行以下操作...

  1. 安装行为已审核
  2. 向创建的审计表中添加一个附加字段:when_processed
  3. 在你的 /lib 文件夹中创建一个名为 processrules 之类的模块,它大致完成此操作

    3.1 抓取所有未处理的审计条目 3.2 将它们标记为已处理(也许此时再做一个小审计表来记录发生的事件)

  4. 现在创建一个规则表,其中只包含名称和条件语句,或者添加一些示例以开始操作

    姓名:第一 |规则语句:'SELECT 1 WHERE table.value = something'

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

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

从这里您可以推断出您需要的附加功能,并且可能会询问有关动态调用方法的元编程方面的另一个问题,因为这个问题非常广泛,非常乐意提供进一步的帮助。

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

【讨论】:

  • +1 - 感谢您提出 Resque。我过去曾研究过它的其他用途,但我并没有想到它对这种情况有多大用处。我也认为你是对的,我自己的滚动可能比尝试破解现有解决方案以使其工作更快/更好。我期待您提供更多反馈!
  • 我添加了一些额外的注释来帮助您破解,也许可以尝试一下这些想法并提出一些新问题,因为当您卡在某个流程上时,我自己或其他人都会非常很高兴帮助一些实际的代码。
  • 感谢您回来提供更多信息!我很感激你把时间花在这上面。接受/赏金奖励 :-) 度过美好的一天!
【解决方案2】:

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

使用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

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

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

【讨论】:

  • +1 - 感谢本的回复。对我来说最重要的是这些规则可能特定于每个客户,因此我无法将所有规则存储在代码中。或者更具体地说,我不能假设所有规则都应该为所有客户端运行。这开辟了一个新的想法......也许我应该在代码中定义所有规则,但在数据库中有一些东西可以指定运行哪些规则。谢谢你的想法;这让我大开眼界!
【解决方案3】:

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

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

【讨论】:

  • +1 - 谢谢 JW,我实际上是从那里开始的,但由于某种原因,我从未找到 Ruleby 的文档。感谢您指点我!
猜你喜欢
  • 1970-01-01
  • 2011-12-02
  • 1970-01-01
  • 1970-01-01
  • 2010-10-23
  • 2010-12-26
  • 2020-04-02
  • 2023-03-12
相关资源
最近更新 更多