注:この問題はlodashに提出しました。問題がうまく解決するのに役立つと確信しているのですが、今は指を触れていません。
さまざまなユーザーロールとその権限を説明するオブジェクトがあります。
「このように」定義された10〜15個のロールのようなものがあります(これはアプリケーションコードを反映していませんが、問題自体):
var role1 = {
views: {
v1: {access: true},
v2: {access: false},
v#: {access: false}
}
}
var role2 = {
views: {
v1: {access: false},
v2: {access: true},
v3: {access: true},
}
}
接続されたユーザーには複数の役割があります。その例では['role1', 'role2']
、そしてこれから、すべてのユーザーロールで定義されたすべての小道具の組み合わせになる単一のpermissions
オブジェクトを構築する必要があります。
これは基本的にホワイトリストベースであり、すべての「true」プロパティはfalseとして定義されたものをオーバーライドする必要があります。したがって、期待される結果は次のようになります。
permissions = {
views: {
v1: {access: true},
v2: {access: true},
v2: {access: true}
}
}
クレイジーなネストされたループに依存せずにそれに対処する方法がわからない
JSBinの出発点を以下に示します。 http://jsbin.com/usaQejOJ/1/edit?js,console
ご協力いただきありがとうございます!
ロダッシュには、この問題をエレガントに解決するのに役立ついくつかの方法があります。
まず、 merge
メソッドです。複数のソースオブジェクトを受け取り、それらのプロパティを再帰的に結合して宛先オブジェクトにします。 2つのオブジェクトが同じプロパティ名を持っている場合、後者の値が前者をオーバーライドします。
これはほとんど私たちが望んでいることです。ロールオブジェクトを1つのオブジェクトにマージします。私たちが望まないのは、そのオーバーライド動作です。 true
の値が常にfalse
の値をオーバーライドするようにします。幸いにも、カスタムマージ関数を渡すことができます。lodashのmerge
は、2つのオブジェクトが同じキーを持っている場合に、それを使用してマージされた値を計算します。
(後でOR
値がfalse
sをオーバーライドできるようにする代わりに)アイテムを論理的にtrue
にするカスタム関数を作成します。これにより、どちらかの値がtrue
、マージされた結果の値はtrue
になります。
オブジェクトは入れ子になっているので、カスタムのマージ関数がブール値を比較する場合にのみ、これを行うようにする必要がありますOR
。オブジェクトを比較するとき、オブジェクトのプロパティの通常のマージを行います(ここでも、カスタム関数を使用してマージを行います)。次のようになります。
function do_merge(roles) {
// Custom merge function ORs together non-object values, recursively
// calls itself on Objects.
var merger = function (a, b) {
if (_.isObject(a)) {
return _.merge({}, a, b, merger);
} else {
return a || b;
}
};
// Allow roles to be passed to _.merge as an array of arbitrary length
var args = _.flatten([{}, roles, merger]);
return _.merge.apply(_, args);
}
do_merge([role1, role2, role3]);
Lodashは別の方法で役立ちます。ドキュメントから、_.merge
がマージするオブジェクトの配列を受け入れないことがわかります。それらを引数として渡す必要があります。しかし、私たちの場合、配列は非常に便利です。
これを回避するには、JavaScriptの apply
メソッドを使用します。これにより、引数を配列として渡してメソッドを呼び出すことができ、Lodashの便利なflatten
メソッドを使用できます、ネストされた配列([1, [2, 3], [4, 5]]
など)を含む可能性のある配列を受け取り、それを[1, 2, 3, 4, 5]
にフラット化します。
したがって、必要なすべての引数をflatten
ed配列にまとめ、_apply
_merge
に渡します。
オブジェクトが非常に深くネストされている場合、このように再帰的にmerger
を呼び出すとスタックがオーバーフローする可能性がありますが、オブジェクトの場合はこれで問題ありません。