【发布时间】:2011-08-27 00:40:35
【问题描述】:
我在面向文档的前面放置了一个安全层,我需要一种合理抽象的方式让应用程序定义哪些新文档以及对现有文档的哪些更新对于特定用户是合法的。
具体问题是 -- 文档被定义(至少在传输中)为 JSON 对象,因此规则可能是分层的,因此规则引擎必须递归工作。例如,Employee 对象可能有一个名为 Compensation 的子对象,而该子对象有一个名为 PayPeriod 的字段,该字段必须是“weekly”、“biweekly”或“monthly”之一。 -- 它运行 Node.js 并且需要从输入中读取一些规则(例如,从数据库中读取更多用户数据),因此它必须以 continuation 样式运行。
所以我想出的是这样的:每个规则都是一个函数,它接受当前值、建议的新值和一个使用要使用的值调用的回调。该值可以是两个输入之一,也可以是规则计算的某个第三个值。这是一条规则:
var nonEmpty = function(proposedValue, existingValue, callback) {
callback( (proposedValue.length > 0) ? proposedValue : existingValue);
};
此规则仅允许您使用非零长度值设置或替换此字段。当然,这只对字符串值有意义(暂时忽略列表,所以我们需要一个规则来强制字符串):
var isString = function(proposedValue, existingValue, callback) {
callback( ( typeof(proposedValue) === 'string') ? proposedValue : existingValue);
};
事实上,这似乎是一种常见的问题,所以我写了一个规则生成器:
var ofType = function(typeName) {
return function(proposedValue, existingValue, callback) {
callback( ( typeof(proposedValue) === typeName) ? proposedValue : existingValue);
};
};
var isString = ofType('string')
但我需要一种将规则串在一起的方法:
var and = function(f1, f2) {
return function(proposedValue, existingValue, callback) {
f1(proposedValue, existingValue,
function(newProposedValue) {
f2(newProposedValue, existingValue, callback);
});
};
};
var nonEmptyString = and(isString, nonEmpty);
因此管理员更新员工记录的规则可能是:
limitedObject({
lastName : nonEmptyString,
firstName : nonEmptyString,
compensation : limitedObject({
payPeriod : oneOf('weekly', 'biweekly', 'monthly'),
pay : numeric
}
})
limitedObject(如ofType)是一个规则生成函数,它只允许在其参数中指定的字段并将给定规则应用于这些字段的值。
所以我写了这一切,它就像一个魅力。我所有的错误都是单元测试中的错误!好吧,几乎所有人。无论如何,如果你已经读到这里,这是我的问题:
我一直在狂热地研究单子,我的阅读启发了我以这种方式解决问题。但是,这真的是单子吗?
(可能的答案:“是”、“不,但这没关系,因为 monad 并不是解决这个问题的真正正确方法”和“不,这就是需要改变的地方”。也欢迎第四种可能性。)
【问题讨论】:
标签: javascript monads