在 Ruby 中指定和执行规则

发布于 2024-12-01 12:19:32 字数 1146 浏览 1 评论 0原文

我正在寻找一个 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 来提高性能)。

在这一点上,看起来我将不得不推出自己的,所以任何关于最好的方法的想法,或者我应该研究的任何工具,将不胜感激。

再次感谢!

I am looking for a Ruby/Rails tool that will help me accomplish the following:

I would like to store the following string, and ones similar to it, in my database. When an object is created, updated, deleted, etc., I want to run through all the strings, check to see if the CRUD event matches the conditions of the string, and if so, run the actions specified.

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

I am planning to create an interface that builds these strings, so it doesn't need to be a human-readable string. If a JSONish structure is better, or a tool has an existing language, that would be fantastic. I'm kinda thinking something along the lines of:

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

So basically, I need the following:

  1. Monitor CRUD events - It would be nice if the tool had a way to do this, but Ican use Rails' ModelObservers here if the tool doesn't natively provide it

  2. Find all matching "rules" - This is my major unknown...

  3. Execute the requested method/parameters - Ideally, this would be defined in my Ruby code as classes/methods

Are there any existing tools that I should investigate?

Edit:

Thanks for the responses so far guys! I really appreciate you pointing me down the right paths.

The use case here is that we have many different clients, with many different business rules. For the rules that apply to all clients, I can easily create those in code (using something like Ruleby), but for all of the client-specific ones, I'd like to store them in the database. Ideally, the rule could be written once, stored either in the code, or in the DB, and then run (using something Resque for performance).

At this point, it looks like I'm going to have to roll my own, so any thoughts as to the best way to do that, or any tools I should investigate, would be greatly appreciated.

Thanks again!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

菩提树下叶撕阳。 2024-12-08 12:19:32

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

我会在接下来的方式,我的想法是,您不想在用户保存时进行规则匹配,因为这可能需要一段时间,并且可能会中断用户体验和/或减慢服务器速度,所以......

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

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

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

Table: Rule

Name

ForEvent (eg. 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. 如果规则匹配,请将其添加到您的日志文件中。

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

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

I don't think it would be a major thing to write something yourself to do this, I don't know of any gems which would do this (but it would be good if someone wrote one!)

I would tackle the project in the following way, the way I am thinking is that you don't want to do the rule matching at the point the user saves as it may take a while and could interrupt the user experience and/or slow up the server, so...

  1. Use observers to store a record each time a CRUD event happens, or to make things simpler use the Acts as Audited gem which does this for you.

1.5. Use a rake task, running from your crontab to run through the latest changes, perhaps every minute, or you could use Resque which does a good job of handling lots of jobs

  1. Create a set of tables which define the possible rules a user could select from, perhaps something like

Table: Rule

Name

ForEvent (eg. CRUD)

TableInQuestion

  • FieldOneName

  • FieldOneCondition etc.

MethodToExecute

You can use a bit of metaprogramming to execute your method and since your method knows your table name and record id then this can be picked up.

Additional Notes

The best way to get going with this is to start simple then work upwards. To get the simple version working first I'd do the following ...

  1. Install acts as audited
  2. Add an additional field to the created audit table, :when_processed
  3. Create yourself a module in your /lib folder called something like processrules which roughly does this

    3.1 Grabs all unprocessed audit entries
    3.2 Marks them as processed (perhaps make another small audit table at this point to record events happening)

  4. Now create a rules table which simply has a name and condition statement, perhaps add a few sample ones to get going

    Name: First | Rule Statement: 'SELECT 1 WHERE table.value = something'

  5. Adapt your new processrules method to execute that sql for each changed entry (perhaps you want to restrict it to just the tables you are working with)

  6. If the rule matched, add it to your log file.

From here you can extrapolate out the additional functionality you need and perhaps ask another question about the metaprogramaming side of dynamically calling methods as this question is quite broad, am more than happy to help further.

I tend to think the best way to go about task processing is to setup the process nicely first so it will work with any server load and situation then plug in the custom bits.

十六岁半 2024-12-08 12:19:32

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

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

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

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

You could make this abstract enough so that you can specify arbitrary conditions and rules, but then you'd be developing a framework/engine as opposed to solving the specific problems of your app.

There's a good chance that using ActiveRecord::Observer will solve your needs, since you can hardcode all the different types of conditions you expect, and then only put the unknowns in the database. For example, say you know that you'll have people watching categories, then create an association like category_watchers, and use the following Observer:

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

If you want to store the email preference along with the fact that the user is watching the category, then use a join model with a flag indicating that.

If you then want to abstract it a step further, I'd suggest using something like treetop to generate the observers themselves, but I'm not convinced that this adds more value than abstracting similar observers in code.

东京女 2024-12-08 12:19:32

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

希望这可以帮助您开始调查。

There's a Ruby & Rules Engines SO post that might have some info that you might find useful. There's another Ruby-based rules engine that you may want to explore that as well - Ruleby.

Hope that this helps you start your investigation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文