使用规则引擎

时间:2015-05-29 11:28:23

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

我有以下情况 -

我有Company我有Incident

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

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

现在针对特定事件,我需要找到所有提供我需要的服务的公司。我希望使用规则引擎来实现这一点,因为我有更复杂的条件来申请选择合适的公司。

我调查了这个名为 - 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模型代替这些字符串?在Ruby on Rails应用程序的上下文中是否有将事实加载到引擎中的最佳实践?

我的用例是,用户选择事件并要求可以为事件提供服务的公司。我需要向规则引擎询问可以解决问题的公司列表:)

1 个答案:

答案 0 :(得分:3)

您可以使用嵌套迭代到引擎来完成此操作。

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

的问题的注释

假设您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