使用规则引擎

Using Rules Engine

我有以下情况 -

我有 Company,我有 Incident

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

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

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

我调查了这个 gem 称为 - Wongi-engine (github.com/ulfurinn/wongi-engine),但我很难围绕它编写规则。

你能给我指点一下吗?谢谢!

我可以想出以下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 模型来代替这些字符串?在 Rails 应用程序的 Ruby 上下文中,是否有将事实加载到引擎中的最佳实践?

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

您可以对引擎进行嵌套迭代。

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

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

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...

的问题添加注释

假设您有 Company 的属性 nameIncident 的属性 nameService 的属性 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