Skip to content
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

Use '.@' at the end of the param, to pass effective path instead of the value #1

Merged
merged 8 commits into from
Jan 31, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/rule.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import {
isArray,
isObject,
isEmpty,
forEach
forEach,
last,
slice
} from 'lodash/fp'
import { isExisty } from './assert'
import { concat, arrayOfArrays, getContextPath } from './utils'
Expand Down Expand Up @@ -57,7 +59,13 @@ const defaultEnabler = [() => true],
},
queryPath = (value, context) => (p) => {
if (isFunction(p)) return p()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is good, my only doubt is that we are taking another symbol "@" as operation. Intention is to make path as less DSL filled as possible. What do you think of another approach, where we can add current path as a parameter to a function here? Not just p() but p(contextPath)?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function as parameter will have something extra in terms of input data, it might be context path and value also

Copy link
Author

@aszu80 aszu80 Jan 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it somewhat more as a "function as decorator" than "function as parameter".

This way we have someting that is looking as functional thing (and for simplicity i decided to go with the creating function that has a special "tag value" assigned as own key).

Other implementations I've done was based on the getPathTo returning object that had "original parameter" and flags (which was effectively pretty much the same as this implementation, but had more lines and ifs) and the "hoc style" that has created new function that was "identifying" itself when it received special argument (and that was too magical, and there was a chance of side effects if someone passed function as a param and if that function had side effects).

The most "stylish" would be probably based on class, then we could check if the object is instance of some our tool class, and then we could use that information to get the path instead of data, but that would then be biggest in the LOC sense, I think.

I agree, this is not ellegant to just "attach" own key to the function, but I think it's a) small, b) easy, c) fast.

return traverse(getContextPath(p, context.indexes), value)
const
contextPath = getContextPath(p, context.indexes)

if (last(contextPath) === '@') {
return slice(0, contextPath.length - 1, contextPath)
}
return traverse(contextPath, value)
},
queryPaths = (params, value, context) =>
map(queryPath(value, context), params),
Expand Down
38 changes: 38 additions & 0 deletions test/rule.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,42 @@ describe('rule', () => {
team: [undefined, undefined, { customName: ['empty'], name: ['empty'] }]
})
})

it('provides path to the processed value', () => {
const
successMap = {
'L.1.1': ['team', '0', 'address', '0'],
'L.2.1': ['team', '1', 'address', '0']
},
rule = {
// -1
value: 'team.address.line1',
params: [
'team.{team}.address.{address}.line1',
'team.{team}.address.{address}.@'
],
test: [
[(v, p1, p2) => {
expect(successMap[p1]).toEqual(p2)
return true
}, 'ERR']
]
},
valForTest = {
team: [
{
address: [
{ line1: 'L.1.1' }
]
},
{
address: [
{ line1: 'L.2.1' }
]
}
]
}

runNormalizedRule(rule, valForTest)
})
})