Skip to content

Commit 4501a6d

Browse files
committed
fix #15
1 parent fec8e60 commit 4501a6d

File tree

5 files changed

+69
-4
lines changed

5 files changed

+69
-4
lines changed

README.md

+16
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,22 @@ let engine = new Engine([{
482482

483483
Validation will automatically catch new extension and work as expected.
484484

485+
## Logic on nested objects
486+
487+
Support of nested structures with [selectn](https://github.com/wilmoore/selectn.js), so basically any query you can define in selectn you can use here.
488+
489+
For example if in previous example, age would be a part of person object, we could work with it like this:
490+
```js
491+
let rules = [ { conditions: { "person.age": { range: [ 20, 40 ] } } } ];
492+
```
493+
494+
Also in order to support systems where keys with "." not allowed (for example if you would like to store data in mongo), you can use `$` to separate references:
495+
496+
For example, this is the same condition, but instead of `.` it uses `$`:
497+
```js
498+
let rules = [ { conditions: { "person$age": { range: [ 20, 40 ] } } } ];
499+
```
500+
485501
## Relevant conditional logic
486502

487503
Sometimes you would want to validate `formData` fields one against the other.

src/conditionsMeet.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import { isObject, toError } from "./utils";
1+
import { isObject, toError, selectRef } from "./utils";
22
import checkField from "./checkField";
33
import { OR, AND, NOT } from "./constants";
4-
import selectn from "selectn";
54

65
export function toRelCondition(refCondition, formData) {
76
if (Array.isArray(refCondition)) {
@@ -12,7 +11,7 @@ export function toRelCondition(refCondition, formData) {
1211
return agg;
1312
}, {});
1413
} else if (typeof refCondition === "string" && refCondition.startsWith("$")) {
15-
return selectn(refCondition.substr(1), formData);
14+
return selectRef(refCondition.substr(1), formData);
1615
} else {
1716
return refCondition;
1817
}
@@ -34,7 +33,7 @@ export default function conditionsMeet(condition, formData) {
3433
} else if (ref === NOT) {
3534
return !conditionsMeet(refCondition, formData);
3635
} else {
37-
let refVal = selectn(ref, formData);
36+
let refVal = selectRef(ref, formData);
3837
if (Array.isArray(refVal)) {
3938
let condMeatOnce = refVal.some(val =>
4039
conditionsMeet(refCondition, val)

src/utils.js

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
import selectn from "selectn";
2+
3+
export function selectRef(field, formData) {
4+
let ref = field.replace(/\$/g, ".");
5+
return selectn(ref, formData);
6+
}
7+
18
export function isObject(obj) {
29
return typeof obj === "object" && obj !== null;
310
}

test/issues/15.test.js

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import Engine from "../../src";
2+
3+
test("support $ single level of nesting", () => {
4+
let rules = [
5+
{
6+
conditions: {
7+
address$zip: { less: 1000 },
8+
},
9+
event: {
10+
type: "match",
11+
},
12+
},
13+
];
14+
let engine = new Engine(rules);
15+
return engine.run({ address: { zip: 10 } }).then(events => {
16+
expect(events.length).toEqual(1);
17+
expect(events[0]).toEqual({ type: "match" });
18+
});
19+
});
20+
21+
test("support $ double level of nesting", () => {
22+
let rules = [
23+
{
24+
conditions: {
25+
person$address$zip: { less: 1000 },
26+
},
27+
event: {
28+
type: "match",
29+
},
30+
},
31+
];
32+
let engine = new Engine(rules);
33+
return engine.run({ person: { address: { zip: 10 } } }).then(events => {
34+
expect(events.length).toEqual(1);
35+
expect(events[0]).toEqual({ type: "match" });
36+
});
37+
});

test/utils.test.js

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
extractRefSchema,
77
isRefArray,
88
toArray,
9+
selectRef,
910
} from "../src/utils";
1011
import { testInProd } from "./utils";
1112

@@ -93,3 +94,8 @@ test("array transformation", () => {
9394
expect(toArray("Yes")).toEqual(["Yes"]);
9495
expect(toArray(["Yes", "No"])).toEqual(["Yes", "No"]);
9596
});
97+
98+
test("select reference", () => {
99+
expect(selectRef("address.zip", { address: { zip: 1000 } })).toEqual(1000);
100+
expect(selectRef("address$zip", { address: { zip: 1000 } })).toEqual(1000);
101+
});

0 commit comments

Comments
 (0)