【问题标题】:Using Rules Engine使用规则引擎
【发布时间】:2015-05-29 11:28:22
【问题描述】:

我有以下情况-

我有CompanyIncident

Company 提供许多服务 (Service),因此 - has_and_belongs_to_many :services

Incident 需要一些服务 (Service),因此 - has_and_belongs_to_many :services

现在,对于给定的事件,我需要找到所有提供我需要的服务的公司。我希望使用规则引擎来执行此操作,因为我有很多更复杂的条件要申请来选择合适的公司。

我研究了这个名为 - Wongi-engine (github.com/ulfurinn/wongi-engine) 的 gem,但是我很难把它包起来并编写规则。

你能给我一些建议吗?谢谢!

我可以想出以下facts

engine << [ "CompanyA", "offers", "serviceA" ]
engine << [ "CompanyB", "offers", "serviceB" ]
engine << [ "CompanyA", "offers", "serviceB" ]
engine << [ "CompanyB", "offers", "serviceC" ]
engine << [ "IncidentA", "requires", "serviceC" ]
engine << [ "IncidentA", "requires", "serviceA" ]

编辑: 另外,一旦我编写了这些规则,如何使用 Rails 模型代替这些字符串?在 Ruby on Rails 应用程序的上下文中将事实加载到引擎中是否有任何最佳实践?

我的用例是,用户选择一个事件并询问可以为该事件提供服务的公司。我需要向规则引擎询问可以做到这一点的公司列表:)

【问题讨论】:

    标签: ruby-on-rails ruby rules rule-engine


    【解决方案1】:

    您可以通过对引擎的嵌套迭代来做到这一点。

    engine.each "IncidentA", "requires" :_  do |requires|
      engine.each :_, "offers", requires.object do |offers|
        puts "IncidentA can get #{requires.object} from #{offers.subject}"
      end
    end
    

    按照惯例这样做...

    suppliers = engine.rule "service suppliers" do
        forall {
            has :Company, "offers", :Service
            has :Incident, "requires", :Service
        }
    end
    

    然后使用规则,选择事件类型并迭代信息。

    suppliers.tokens.select{|s| s[:Incident] == "IncidentA" }.each do |s|
      puts "#{s[:Incident} can get #{s[:Service]} from #{s[:Company]}"
    end
    

    将其作为查询...

    q = engine.query "companies" do
      search_on :Incident
      forall {
          has :Company, "offers", :Service
          has :Incident, "requires", :Service
      }
    end
    
    engine.execute "companies", { Incident: "IncidentA" }
    q.tokens.each do |s|
      puts "#{s[:Incident} can get #{s[:Service]} from #{s[:Company]}"
    end
    

    编辑为您关于填充facts的问题添加注释...

    假设您有Companyname 属性IncidentnameService 属性name

    Company.joins(:services).select("companies.*, services.name as service_name").each do |company|
      engine << [company.name, "offers", company.service_name]
    end
    
    Incident.joins(:services).select("incidents.*, services.name as service_name").each do |incident|
      engine << [incident.name, "requires", incident.service_name]
    end
    

    【讨论】:

    • 太棒了。谢谢你。现在所有这些都变得更有意义了。我会尝试将其合并到我的应用程序中。
    • 还有一件事,我如何将它与我的 Rails 应用程序集成在一起,在那里我将拥有服务、事件和公司模型?将事实加载到引擎中是否有任何好的做法?谢谢!!用这部分编辑问题:)
    • 好的,我已经修改了问题以展示如何使用一些 ActiveModel 内部连接来填充事实。
    • 谢谢! :) 史蒂夫,还有一件事。将这些事实保存在数据库中或在我们需要查询或将它们缓存在 Redis 中时加载它们是一种好习惯吗?你有什么建议?顺便说一句,接受了你的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-23
    相关资源
    最近更新 更多