-
Notifications
You must be signed in to change notification settings - Fork 181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement no-loop rule attribute #163
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -94,6 +94,20 @@ var ruleTokens = { | |
}; | ||
})(), | ||
|
||
noLoop: (function () { | ||
var noLoopRegexp = /^(noLoop|no-loop)\s*:\s*(-?true|false)\s*[,;]?/; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is the |
||
return function (src, context) { | ||
if (noLoopRegexp.test(src)) { | ||
var parts = src.match(noLoopRegexp); | ||
// | ||
context.options.noLoop = Boolean(parts[2]) | ||
return src.replace(parts[0], ""); | ||
} else { | ||
throw new Error("invalid format"); | ||
} | ||
}; | ||
})(), | ||
|
||
"agenda-group": function () { | ||
return this.agendaGroup.apply(this, arguments); | ||
}, | ||
|
@@ -102,6 +116,10 @@ var ruleTokens = { | |
return this.autoFocus.apply(this, arguments); | ||
}, | ||
|
||
"no-loop": function () { | ||
return this.noLoop.apply(this, arguments); | ||
}, | ||
|
||
priority: function () { | ||
return this.salience.apply(this, arguments); | ||
}, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,7 @@ Or [download the source](https://raw.github.com/C2FO/nools/master/nools.js) ([mi | |
* [Structure](#rule-structure) | ||
* [Salience](#rule-salience) | ||
* [Scope](#rule-scope) | ||
* [no-loop](#rule-no-loop) | ||
* [Constraints](#constraints) | ||
* [Not](#not-constraint) | ||
* [Or](#or-constraint) | ||
|
@@ -1001,6 +1002,33 @@ flow1 | |
}); | ||
``` | ||
|
||
<a name="rule-no-loop"></a> | ||
### No-Loop | ||
|
||
When a rule's action modifies a fact it may cause the rule to activate again, causing an infinite loop. Setting no-loop to true will skip the creation of another Activation for the rule with the current set of facts. | ||
|
||
```javascript | ||
this.rule("Hello", {noLoop: true}, [Message, "m", "m.text like /hello/"], function (facts) { | ||
var m = facts.m; | ||
m.text = 'hello world'; | ||
this.modify(m) | ||
}); | ||
|
||
``` | ||
Or using the DSL | ||
|
||
```javascript | ||
rule Hello { | ||
no-loop: true; | ||
when { | ||
m: Message m.name like /hello/; | ||
} | ||
then { modify(m, function() { | ||
m.text = 'hello world' | ||
}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think your missing a
|
||
} | ||
``` | ||
|
||
|
||
|
||
<a name="rule-scope"></a> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
"use strict"; | ||
var it = require("it"), | ||
assert = require("assert"), | ||
nools = require("../../"); | ||
|
||
it.describe("no-loop", function (it) { | ||
/*jshint indent*/ | ||
function Message(name) { | ||
this.name = name; | ||
} | ||
var cnt = 0; | ||
|
||
var flow1 = nools.flow("noLoop1", function () { | ||
|
||
this.rule("Hello2", { noLoop: true }, [Message, "m", "m.name =~ /Hello/"], function (facts) { | ||
var m = facts.m; | ||
m.name = 'Hello World'; | ||
this.modify(m); | ||
}); | ||
}), | ||
|
||
flow2 = nools.flow("noLoop2", function () { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be in line with the flow1 definition For example var flow1 = ...,
flow2 = ...; |
||
|
||
this.rule("Hello1", [Message, "m", "m.name =~ /Hello/"], function (facts) { | ||
var m = facts.m; | ||
if (cnt++ < 2) { | ||
m.name = 'Hello World'; | ||
this.modify(m); | ||
} | ||
}); | ||
}); | ||
|
||
var noolsSource = "rule 'Hello3' { no-loop: true; when {m: Message m.name =~/Hello/;}then {modify(m, function () { this.name = 'Hello World'; });}}"; | ||
|
||
var flow3 = nools.compile(noolsSource, { | ||
name: 'testDsl' | ||
,define: { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comma should be on the previous line |
||
Message: Message | ||
} | ||
}); | ||
|
||
it.should("not loop with option on and loop otherwise", function () { | ||
var fired1 = [], fired2 = [], fired3 = []; | ||
var session1 = flow1.getSession(new Message("Hello")).on("fire", function (name) { | ||
fired1.push(name); | ||
}), | ||
session2 = flow2.getSession(new Message("Hello")).on("fire", function (name) { | ||
fired2.push(name); | ||
}), | ||
session3 = flow3.getSession(new Message("Hello")).on("fire", function (name) { | ||
fired3.push(name); | ||
}); | ||
return session1.match() | ||
.then(function () { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please reformat this block, very hard to figure out how the braces match up. |
||
return session2.match().then(function () { | ||
return session3.match().then(function () { | ||
}) | ||
}) | ||
}) | ||
.then(function () { | ||
assert.deepEqual(fired1, ["Hello2"]); | ||
assert.deepEqual(fired2, ["Hello1", "Hello1", "Hello1"]); | ||
assert.deepEqual(fired3, ["Hello3"]); | ||
}); | ||
}); | ||
|
||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Formatting