如何在 Javascript 中使用 Ramda 将此嵌套 if 函数转换为函数式编程
How can I turn this nested if function into functional style programming with Ramda in Javascript
我正在查看 Prisma 中用于软删除中间件的代码:
prisma.$use(async (params, next) => {
// Check incoming query type
if (params.model == 'Post') {
if (params.action == 'delete') {
// Delete queries
// Change action to an update
params.action = 'update'
params.args['data'] = { deleted: true }
}
if (params.action == 'deleteMany') {
// Delete many queries
params.action = 'updateMany'
if (params.args.data != undefined) {
params.args.data['deleted'] = true
} else {
params.args['data'] = { deleted: true }
}
}
}
return next(params)
})
它的步骤是:
检查 Post -> 如果它是 'delete' 或 'deleteMany' 然后将操作更改为 'update' 并将 deleted 设置为 true.
嵌套的 if 似乎不太理想,而且使用函数式风格似乎会更干净,所以我使用 Ramda 来尝试让它发挥作用:
const model = lensProp('model')
const action = lensProp('action')
const argsData = compose(lensProp('args'), lensProp('data'))
const cView = curry(view)
const modelView = cView(model)
const actionView = cView(action)
const _shouldBeModified = (models, actions, p) => and(
includes(modelView(p), models),
includes(actionView(p), actions)
)
const shouldBeModified = curry(_shouldBeModified)
const timeElapsed = Date.now();
const today = new Date(timeElapsed);
const softDelete = (models, actions, params) => ifElse(
shouldBeModified(models, actions),
pipe(
set(argsData, { deleted: true, deletedAt: today.toISOString()}),
set(action, 'update')
),
identity
)(params)
然后我可以这样称呼它:
softDelete(['Post'],['delete', 'deleteMany'],params)
/*
returns: {"action": "update", "args": {"data": {"deleted": true, "deletedAt": "2022-04-17T19:49:00.294Z"}}, "model": "Post"}
*/
综上所述,我是 Ramda 的新手,我的方法似乎很乱,有人可以帮我清理一下吗?
您可以使用 R.when
和 R.where
来检查 params
是否应该更新。如果是这样,请使用 R.evolve
更新它们。
传递一个 actions
对象,而不是一个数组,因此代码可以根据原始操作映射 update
/ updateMany
。
const { curry, when, where, includes, __, keys, evolve, prop, mergeDeepLeft } = R
const actionsMap = { delete: 'update', deleteMany: 'updateMany' };
const softDelete = curry((models, actions, params) => when(
where({
model: includes(__, models),
action: includes(__, keys(actions))
}),
evolve({
action: prop(__, actions),
args: mergeDeepLeft({ data: { deleted: true, deletedAt: new Date().toISOString() }})
})
)(params))
const params = {"action": "deleteMany", "args": { data: { something: 5 } }, "model": "Post"}
const result = softDelete(['Post'], actionsMap, params)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js" integrity="sha512-t0vPcE8ynwIFovsylwUuLPIbdhDj6fav2prN9fEu/VYBupsmrmk9x43Hvnt+Mgn2h5YPSJOk7PMo9zIeGedD1A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
我正在查看 Prisma 中用于软删除中间件的代码:
prisma.$use(async (params, next) => {
// Check incoming query type
if (params.model == 'Post') {
if (params.action == 'delete') {
// Delete queries
// Change action to an update
params.action = 'update'
params.args['data'] = { deleted: true }
}
if (params.action == 'deleteMany') {
// Delete many queries
params.action = 'updateMany'
if (params.args.data != undefined) {
params.args.data['deleted'] = true
} else {
params.args['data'] = { deleted: true }
}
}
}
return next(params)
})
它的步骤是: 检查 Post -> 如果它是 'delete' 或 'deleteMany' 然后将操作更改为 'update' 并将 deleted 设置为 true.
嵌套的 if 似乎不太理想,而且使用函数式风格似乎会更干净,所以我使用 Ramda 来尝试让它发挥作用:
const model = lensProp('model')
const action = lensProp('action')
const argsData = compose(lensProp('args'), lensProp('data'))
const cView = curry(view)
const modelView = cView(model)
const actionView = cView(action)
const _shouldBeModified = (models, actions, p) => and(
includes(modelView(p), models),
includes(actionView(p), actions)
)
const shouldBeModified = curry(_shouldBeModified)
const timeElapsed = Date.now();
const today = new Date(timeElapsed);
const softDelete = (models, actions, params) => ifElse(
shouldBeModified(models, actions),
pipe(
set(argsData, { deleted: true, deletedAt: today.toISOString()}),
set(action, 'update')
),
identity
)(params)
然后我可以这样称呼它:
softDelete(['Post'],['delete', 'deleteMany'],params)
/*
returns: {"action": "update", "args": {"data": {"deleted": true, "deletedAt": "2022-04-17T19:49:00.294Z"}}, "model": "Post"}
*/
综上所述,我是 Ramda 的新手,我的方法似乎很乱,有人可以帮我清理一下吗?
您可以使用 R.when
和 R.where
来检查 params
是否应该更新。如果是这样,请使用 R.evolve
更新它们。
传递一个 actions
对象,而不是一个数组,因此代码可以根据原始操作映射 update
/ updateMany
。
const { curry, when, where, includes, __, keys, evolve, prop, mergeDeepLeft } = R
const actionsMap = { delete: 'update', deleteMany: 'updateMany' };
const softDelete = curry((models, actions, params) => when(
where({
model: includes(__, models),
action: includes(__, keys(actions))
}),
evolve({
action: prop(__, actions),
args: mergeDeepLeft({ data: { deleted: true, deletedAt: new Date().toISOString() }})
})
)(params))
const params = {"action": "deleteMany", "args": { data: { something: 5 } }, "model": "Post"}
const result = softDelete(['Post'], actionsMap, params)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js" integrity="sha512-t0vPcE8ynwIFovsylwUuLPIbdhDj6fav2prN9fEu/VYBupsmrmk9x43Hvnt+Mgn2h5YPSJOk7PMo9zIeGedD1A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>