Have any of you had any experience using any Rules Engine libraries? I'm working on a game and I'm trying to separate rule logic from application logic to let me easily test variations of game rules.<p>The game is built in Rails, but I'd like to hear about experience with any language.<p>Things I'm interested in:
-How the rules logically fit into the rest of the application (especially with MVC apps)
-How the rules are stored (ie, in db table, yaml file, ruby file, etc)
-Schema
-Anything else!<p>Thanks!
I've used Drools: <a href="http://www.jboss.org/drools/" rel="nofollow">http://www.jboss.org/drools/</a><p>It's a deductive rules engine for Java, so you give it some objects with state and apply a set of first-order(ish) logic rules to them, in an if-then kind of form. You can give rules different precedence levels to create a sort of cascading effect.<p>Rules are stored in plain text, but they're read in and compiled into memory for efficient execution. Defining your own DSL spec is a breeze. Your rules are executed in the rest of the application with a few simple method calls. It integrates with Java in a really slick way, so you can work with POJOs and your rules operate on them.<p>It's a pretty cool DSL creator, actually. I used it in a research project by integrating it with the Eclipse JDT and creating a DSL for source code manipulation. Then I hooked it up to a little inference algorithm we created, and the result was a plug-in which could take a before and after piece of code, analyze the difference between the two (specifically in the case of adding annotations to legacy code), and generate a set of Drools rules that could automatically migrate similar legacy classes. See page 5 of our paper for an example of how our DSL rule base looked: <a href="http://people.cs.vt.edu/~tilevich/papers/rosemari-oopsla.pdf" rel="nofollow">http://people.cs.vt.edu/~tilevich/papers/rosemari-oopsla.pdf</a>
I was just involved in a port of a Rules Engine for a top US bank. The engine was written in Smalltalk. To make a very long story short, most of the rule components had a 1-to-1 translation to a Smalltalk code block (or collection of blocks), which was then compiled and executed. This would be a great way to implement a Rules engine in Ruby. Define a very simple language, all of whose components have a 1-to-1 mapping to a small subset of Ruby. Generate the Ruby code and compile it. If your subset is kept simple, you can easily use a compiler-compiler or just hand code a top-down parser. With a strict subset of Ruby, you could also make everything a method and get the s-expression for each method instead of parsing it yourself, but this makes it less straightforward to restrict your subset of Ruby to exactly what you want. (You may want such restrictions if you have non-programmers maintaing the rules.)<p>The framework I was working with also had components where arbitrary Smalltalk code could be used. In retrospect, this is a bad idea.<p>All of the rule components were stored as strings with bits of metadata using an Object Relational framework.<p>Also note that the entire Rules repository only amounted to about 5MB of compressed data. I suspect this isn't unusually small. Rules can be cached locally with the system only checking for updates.<p>(EDIT: DO NOT naively think you can use a bunch of regexps instead of a parser of some kind. You can make this work, but it's a hack. If you don't know enough about automata and languages to know why this wouldn't work, you probably don't know enough to be certain about the results of such a hack.)
Hey thanks for all your answers to far!
Here's what I've been working with (sorry if this only makes sense to Rails folks--ask me about a certain section, and I'll try to clarify to non-Rails people as best I can):
-A ruby gem called rools
-sample rule:<p><pre><code> rule 'foo' do
parameter SomeObject
condition { some_object.attribute == 'something_else' }
consequence { some_object.change_state! }
end</code></pre>
-inside of the application_controller, I run a before_filter with this code:<p><pre><code> rules = Rools:RuleSet.new 'path/to/file/that/has/rules.rb'
so = SomeObject.find(:first)
rules.assert so</code></pre>