Skip to content

Commit 91e82a0

Browse files
committed
refactored remove rule and added updateRule
1 parent d27e402 commit 91e82a0

File tree

3 files changed

+65
-17
lines changed

3 files changed

+65
-17
lines changed

docs/engine.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ undefined facts as `undefined`. (default: false)
4444

4545
`pathResolver` - Allows a custom object path resolution library to be used. (default: `json-path` syntax). See [custom path resolver](./rules.md#condition-helpers-custom-path-resolver) docs.
4646

47+
`ruleKeyField` - By default this field is set to 'id', this field is the rule property that will be used when removing a rule by a key string or when updating rule
48+
4749
### engine.addFact(String id, Function [definitionFunc], Object [options])
4850

4951
```js
@@ -73,6 +75,7 @@ engine.removeFact('speed-of-light')
7375
### engine.addRule(Rule instance|Object options)
7476

7577
Adds a rule to the engine. The engine will execute the rule upon the next ```run()```
78+
if the rule doesn't have value set at rule[engine.ruleKeyField], a random string will be set instead.
7679

7780
```js
7881
let Rule = require('json-rules-engine').Rule
@@ -102,6 +105,22 @@ engine.addRule(rule)
102105

103106
//remove it
104107
engine.removeRule(rule)
108+
//or
109+
engine.removeRule(rule.id)
110+
```
111+
112+
### engine.updateRule(Rule instance|Object options)
113+
114+
Updates a rule in the engine.
115+
116+
```javascript
117+
// adds a rule
118+
let rule = new Rule()
119+
engine.addRule(rule)
120+
rule.conditions.all = []
121+
122+
//update it
123+
engine.updateRule(rule)
105124
```
106125

107126
### engine.addOperator(String operatorName, Function evaluateFunc(factValue, jsonValue))

src/engine.js

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class Engine extends EventEmitter {
2525
this.operators = new Map()
2626
this.facts = new Map()
2727
this.status = READY
28+
this.ruleKeyField = options.ruleKeyField || 'id'
2829
rules.map(r => this.addRule(r))
2930
defaultOperators.map(o => this.addOperator(o))
3031
}
@@ -47,27 +48,44 @@ class Engine extends EventEmitter {
4748
} else {
4849
if (!Object.prototype.hasOwnProperty.call(properties, 'event')) throw new Error('Engine: addRule() argument requires "event" property')
4950
if (!Object.prototype.hasOwnProperty.call(properties, 'conditions')) throw new Error('Engine: addRule() argument requires "conditions" property')
50-
5151
rule = new Rule(properties)
5252
}
5353
rule.setEngine(this)
54-
54+
if (!rule[this.ruleKeyField]) rule[this.ruleKeyField] = '_' + Math.random().toString(36).substr(2, 9)
5555
this.rules.push(rule)
5656
this.prioritizedRules = null
5757
return this
5858
}
5959

6060
/**
61-
* Remove a rule from the engine
61+
* update a rule in the engine
6262
* @param {object|Rule} rule - rule definition. Must be a instance of Rule
6363
*/
64-
removeRule (rule) {
65-
if ((rule instanceof Rule) === false) throw new Error('Engine: removeRule() rule must be a instance of Rule')
64+
updateRule (rule) {
65+
const ruleIndex = this.rules.findIndex(ruleInEngine => ruleInEngine[this.ruleKeyField] === rule[this.ruleKeyField])
66+
if (ruleIndex > -1) {
67+
this.rules.splice(ruleIndex, 1)
68+
this.addRule(rule)
69+
} else {
70+
throw new Error('Engine: updateRule() rule not found')
71+
}
72+
}
6673

67-
const index = this.rules.indexOf(rule)
68-
if (index === -1) return false
69-
this.prioritizedRules = null
70-
return Boolean(this.rules.splice(index, 1).length)
74+
/**
75+
* Remove a rule from the engine
76+
* @param {object|Rule||string} rule - rule definition. Must be a instance of Rule
77+
*/
78+
removeRule (rule) {
79+
if (!(rule instanceof Rule)) {
80+
this.rules = this.rules.filter(ruleInEngine => ruleInEngine[this.ruleKeyField] !== rule)
81+
this.prioritizedRules = null
82+
return Boolean(this.rules.length)
83+
} else {
84+
const index = this.rules.indexOf(rule)
85+
if (index === -1) return false
86+
this.prioritizedRules = null
87+
return Boolean(this.rules.splice(index, 1).length)
88+
}
7189
}
7290

7391
/**

test/engine.test.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,17 @@ describe('Engine', () => {
8484
})
8585
})
8686

87+
describe('updateRule()', () => {
88+
it('updates rule', () => {
89+
const rule = new Rule(factories.rule())
90+
engine.addRule(rule)
91+
expect(engine.rules[0].conditions.all.length).to.equal(2)
92+
rule.conditions = { all: [] }
93+
engine.updateRule(rule)
94+
expect(engine.rules[0].conditions.all.length).to.equal(0)
95+
})
96+
})
97+
8798
describe('removeRule()', () => {
8899
describe('rule instance', () => {
89100
it('removes the rule', () => {
@@ -96,14 +107,6 @@ describe('Engine', () => {
96107
})
97108
})
98109

99-
describe('required fields', () => {
100-
it('.conditions', () => {
101-
expect(() => {
102-
engine.removeRule([])
103-
}).to.throw(/Engine: removeRule\(\) rule must be a instance of Rule/)
104-
})
105-
})
106-
107110
it('can only remove added rules', () => {
108111
expect(engine.rules.length).to.equal(0)
109112
const rule = new Rule(factories.rule())
@@ -118,6 +121,14 @@ describe('Engine', () => {
118121
engine.removeRule(rule)
119122
expect(engine.prioritizedRules).to.equal(null)
120123
})
124+
it('removes rule based on ruleKey', () => {
125+
const rule = new Rule(factories.rule())
126+
engine.addRule(rule)
127+
expect(engine.rules.length).to.equal(1)
128+
engine.removeRule(rule.id)
129+
expect(engine.rules.length).to.equal(0)
130+
expect(engine.prioritizedRules).to.equal(null)
131+
})
121132
})
122133

123134
describe('addOperator()', () => {

0 commit comments

Comments
 (0)