Ruby rule mechanism

It seems to me that I'm going to invent a wheel here, so before I do this ...

I have a large set of data that I need to process, and the "rules" that process the data will change over time, so I thought that implementing a simple rule engine would be fine.

Note I'm not looking for a natural language parser , I want all the rules to be ruby ​​procs.

I could imagine that the syntax looks something like this:

engine = SimpleRulesEngine.new rule = engine.add_rule(priority: 10) do |row| row.name != 'George' end rule.action do |row| puts "Yikes, name is not George!, it was #{row.name}" row.update_attribute :name, 'George' end engine.process collection 

I was wondering if there are any existing patterns or gems to help with this. The one that seems closest is ruleby , but doesn't seem to be actively supported and seems to be too complicated a solution for my problem.

Thanks!


Note that this is a similar question: Ruby and Rules Engines , but unlike that, I don't care about natural language processing and storing rules.

+7
source share
5 answers

@DaveNewton told me about some reason, and it’s clear that basically I was looking for a simple DSL for my application, what I ended up using is very simple, but you can use it for someone else:

 # /lib/simple_rules_engine # To use, just include it in any file where you need some rules engine love ... # then defile rules like so: # # rule :name_of_rule, # priority: 10, # validate: lambda {|o| # do something with o} # fail: lambda {|o| o.fail!}} # # then to run the engine # process_rules(your_data_set) # module SimpleRulesEngine extend ActiveSupport::Concern included do class_attribute :rules self.rules = [] end module ClassMethods # rule :name_of_rule, # priority: 10, # validate: lambda {|o| # do something with o} # fail: lambda {|o| o.fail!}} def rule(name,options={}) self.rules << SimpleRulesEngine::Rule.new(name,options) end def process_rules(collection) collection.each do |row| rules.sort_by(&:priority).each do |rule| rule.run(row) end row.valid! end end end ## Helper Classes class Rule attr_accessor :priority attr_accessor :name # proc to test attr_accessor :validate # if valid attr_accessor :success # if invalid attr_accessor :fail NO_OP = lambda {|o| true } def initialize(name, options={}) self.name = name self.priority = options[:priority] || 10 self.validate = options[:validate] || NO_OP self.fail = options[:fail] || NO_OP self.success = options[:success] || NO_OP end def run(data) if validate.call(data) success.call(data) else fail.call(data) end end end end 
+6
source

Perhaps look at Wongi as suggested by Stratus3D. At first glance it looks beautiful and has a good introduction. I will conduct it on a more complex test screen in the next few weeks.

On the other hand, the runes seem unsupported (the rubyforge page is dead, all the forks I found were also dead).

+1
source

Compared to other existing Ruby rule engines, Ruleby seems to be the most actively supported:

However, the Wongi Engine looks promising and could be what you need.

0
source

I have been playing with Ruleby for several weeks, and it is not too difficult to use, although where I added complications, the massive case argument is used to programmatically load the rules into the engine.

As soon as you understand that the facts are constantly stored in the engine, and each subsequent run not only evaluates the facts that you just invested, but also the facts that you stated earlier, but this is quite straightforward. I am not a fan of how black the area is, although when I get a runtime error, it is an absolute pain to troubleshoot (since I'm currently with one part).

0
source

Don't forget about the pearl of the wongi-engine ( https://github.com/ulfurinn/wongi-engine ). It is based on the Rete algorithm ( http://en.wikipedia.org/wiki/Rete_algorithm/ ) and has a syntax similar to what you are looking for.

0
source

All Articles