Skip to content

Commit

Permalink
v0.4.1
Browse files Browse the repository at this point in the history
* Fixed issue with `CustomConstraint` not binding `this.assert` to `this`. #146 - @raymondfeng
* Added more tests for custom constraints
* Updated readme to include docs about custom constraints.
  • Loading branch information
doug-martin committed Mar 2, 2015
1 parent 2c6d31b commit 51fbe1e
Show file tree
Hide file tree
Showing 12 changed files with 143 additions and 25 deletions.
1 change: 1 addition & 0 deletions .npmignore
Expand Up @@ -2,3 +2,4 @@ node_modules
nools.iml
.idea
atlassian-ide-plugin.xml
examples
6 changes: 6 additions & 0 deletions docs/History.html
Expand Up @@ -178,6 +178,12 @@



<h1>0.4.1</h1>
<ul>
<li>Fixed issue with <code>CustomConstraint</code> not binding <code>this.assert</code> to <code>this</code>. <a href="https://github.com/C2FO/nools/pull/146">#146</a> - <a href="https://github.com/raymondfeng">@raymondfeng</a></li>
<li>Added more tests for custom constraints</li>
<li>Updated readme to include docs about custom constraints.</li>
</ul>
<h1>0.4.0</h1>
<ul>
<li>Fix for issue <a href="https://github.com/C2FO/nools/issues/122">#122</a> referencing defined class within another defined class<ul>
Expand Down
27 changes: 27 additions & 0 deletions docs/index.html
Expand Up @@ -216,6 +216,7 @@ <h1>Usage</h1>
<li><a href="#rule-salience">Salience</a></li>
<li><a href="#rule-scope">Scope</a></li>
<li><a href="#constraints">Constraints</a><ul>
<li><a href="#custom-contraints">Custom</a></li>
<li><a href="#not-constraint">Not</a></li>
<li><a href="#or-constraint">Or</a></li>
<li><a href="#from-constraint">From</a></li>
Expand Down Expand Up @@ -1098,6 +1099,32 @@ <h3>Constraints</h3>
<li><p>Reference(optional) - An object where the keys are properties on the current object, and values are aliases to use. The alias may be used in succeeding patterns.</p>
</li>
</ol>
<p><a name="custom-contraints"></a></p>
<h4>Custom Constraint</h4>
<p>When declaring your rules progrmmatically you can also use a function as a constraint. The function will be called with an object containing each fact that has matched previous constraints.</p>
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">var HelloFact = declare({
instance: {
value: true,
constructor: function (value) {
this.value = value;
}
}
});

var flow = nools.flow(&quot;custom contraint&quot;, function (flow) {
flow.rule(&quot;hello rule&quot;, [HelloFact, &quot;h&quot;, function (facts) {
return facts.h.value === true;
}], function (facts) {
console.log(facts.h.value); //always true
});
});

var session = flow.getSession();
session.assert(new HelloFact(false));
session.assert(new HelloFact(true));
session.match().then(function(){
console.log(&quot;DONE&quot;);
});</code></pre>
<p><a name="not-constraint"></a></p>
<h4>Not Constraint</h4>
<p>The <code>not</code> constraint allows you to check that particular <code>fact</code> does <strong>not</strong> exist.</p>
Expand Down
4 changes: 2 additions & 2 deletions docs/nools.js

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions history.md
@@ -1,3 +1,9 @@
# 0.4.1

* Fixed issue with `CustomConstraint` not binding `this.assert` to `this`. [#146](https://github.com/C2FO/nools/pull/146) - [@raymondfeng](https://github.com/raymondfeng)
* Added more tests for custom constraints
* Updated readme to include docs about custom constraints.

# 0.4.0

* Fix for issue [#122](https://github.com/C2FO/nools/issues/122) referencing defined class within another defined class
Expand Down
1 change: 1 addition & 0 deletions nools.js
Expand Up @@ -983,6 +983,7 @@ Constraint.extend({
this.type = "custom";
this.fn = func;
this.options = options;
extd.bindAll(this, ["assert"]);
},

equal: function (constraint) {
Expand Down
4 changes: 2 additions & 2 deletions nools.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
@@ -1,7 +1,7 @@
{
"name": "nools",
"description": "A rules engine for node",
"version": "0.4.0",
"version": "0.4.1",
"bin": {
"nools": "./bin/nools"
},
Expand Down
34 changes: 34 additions & 0 deletions readme.md
Expand Up @@ -38,6 +38,7 @@ Or [download the source](https://raw.github.com/C2FO/nools/master/nools.js) ([mi
* [Salience](#rule-salience)
* [Scope](#rule-scope)
* [Constraints](#constraints)
* [Custom](#custom-contraints)
* [Not](#not-constraint)
* [Or](#or-constraint)
* [From](#from-constraint)
Expand Down Expand Up @@ -1161,6 +1162,39 @@ when {

4. Reference(optional) - An object where the keys are properties on the current object, and values are aliases to use. The alias may be used in succeeding patterns.

<a name="custom-contraints"></a>

#### Custom Constraint

When declaring your rules progrmmatically you can also use a function as a constraint. The function will be called with an object containing each fact that has matched previous constraints.


```javascript
var HelloFact = declare({
instance: {
value: true,
constructor: function (value) {
this.value = value;
}
}
});

var flow = nools.flow("custom contraint", function (flow) {
flow.rule("hello rule", [HelloFact, "h", function (facts) {
return facts.h.value === true;
}], function (facts) {
console.log(facts.h.value); //always true
});
});

var session = flow.getSession();
session.assert(new HelloFact(false));
session.assert(new HelloFact(true));
session.match().then(function(){
console.log("DONE");
});
```

<a name="not-constraint"></a>
#### Not Constraint

Expand Down
8 changes: 8 additions & 0 deletions test/constraintMatcher.test.js
Expand Up @@ -497,6 +497,14 @@ it.describe("constraint matcher", function (it) {
assert.equal(atoms[0].type, "reference");
});

it.should("return a custom CustomConstraint if called with a function", function(){
var atoms = constraintMatcher.toConstraints(function(){
return true
});
assert.lengthOf(atoms, 1);
assert.equal(atoms[0].type, "custom");
});

});

it.describe("#toJs", function (it) {
Expand Down
35 changes: 35 additions & 0 deletions test/flow/custom.test.js
@@ -0,0 +1,35 @@
"use strict";
var it = require("it"),
assert = require("assert"),
declare = require("declare.js"),
nools = require("../../");
it.describe("custom contraint rule", function (it) {

var called = 0;
var HelloFact = declare({
instance: {
value: true,
constructor: function (value) {
this.value = value;
}
}
});

var flow = nools.flow("custom contraint", function (flow) {
flow.rule("hello rule", [HelloFact, "h", function (facts) {
return !!facts.h.value;
}], function () {
called++;
});
});

it.should("call hello world rule", function () {
var session = flow.getSession();
session.assert(new HelloFact(false));
session.assert(new HelloFact(true));
return session.match().then(function () {
assert.equal(called, 1);
});
});

});
40 changes: 20 additions & 20 deletions test/rules.test.js
Expand Up @@ -430,34 +430,34 @@ it.describe("Rule", function (it) {

it.describe("custom function as constraints", function (it) {

var MyConstraint = function(fact) {
return true;
};
function customContraint(fact) {
return true;
};

it.should("create for String function with custom constraint", function() {
var rule = rules.createRule("My Rule", [String, "s", MyConstraint], cb);
assert.isNotNull(rule);
assert.lengthOf(rule, 1);
rule = rule[0];
assert.equal(rule.name, "My Rule");
assert.isNotNull(rule.pattern);
var pattern = rule.pattern;
assert.equal(pattern.alias, "s");
assert.lengthOf(pattern.constraints, 2);
assert.instanceOf(pattern.constraints[0], constraints.ObjectConstraint);
assert.equal(pattern.constraints[0].constraint, String);
assert.instanceOf(pattern.constraints[1], constraints.CustomConstraint);
assert.strictEqual(rule.cb, cb);
});
it.should("create for String function with custom constraint", function () {
var rule = rules.createRule("My Rule", [String, "s", customContraint], cb);
assert.isNotNull(rule);
assert.lengthOf(rule, 1);
rule = rule[0];
assert.equal(rule.name, "My Rule");
assert.isNotNull(rule.pattern);
var pattern = rule.pattern;
assert.equal(pattern.alias, "s");
assert.lengthOf(pattern.constraints, 2);
assert.instanceOf(pattern.constraints[0], constraints.ObjectConstraint);
assert.equal(pattern.constraints[0].constraint, String);
assert.instanceOf(pattern.constraints[1], constraints.CustomConstraint);
assert.strictEqual(rule.cb, cb);
});
});

it.describe("custom type via scope", function (it) {

var MyType = function(name) {
var MyType = function (name) {
this.name = name;
};

it.should("create for String function with custom constraint", function() {
it.should("create for String function with custom constraint", function () {
var rule = rules.createRule("My Rule", {scope: {MyType: MyType}}, ['MyType', "s", "s.name === 'X'"], cb);
assert.isNotNull(rule);
assert.lengthOf(rule, 1);
Expand Down

0 comments on commit 51fbe1e

Please sign in to comment.