密集したコードであることは間違いありません。だから、あなたが言うようbefore
にafter
、パラメータとしてメソッドに渡されるハッシュ(のような?)オブジェクトです。呼び出すbefore.diff(after)
と別のハッシュが返され、すぐに.keys
呼び出されます。これにより、返されたハッシュ内のすべてのキーがdiff
返されます。キーは配列として返され、すぐにソートされます。
次に、最も複雑で密度の高いビットに到達します。inject
そのソートされたキーの配列を使用して、メソッドはメソッドの戻り値となる配列を作成します (ブロックdiffs
内で呼び出されます) 。inject
inject
その配列は、相違点の記録で構成されています。before.diff(after)
各レコードはハッシュであり、戻り値からソートされたキーの配列から 1 つのキーを取得することによって構築されます。これらのハッシュには、比較対象の属性、前のハッシュでどのように見えるか、後のハッシュでどのように見えるかが格納されます。
簡単に言うと、このメソッドは 2 つのハッシュ間の違いを取得し、それらをハッシュの配列にまとめます。そのハッシュの配列は、メソッドの最終的な戻り値です。
注:inject
これよりもはるかに単純である可能性があり、多くの場合は単純です。通常、1 つの操作を繰り返し適用し、結果をアキュムレータに格納することにより、値のコレクションを 1 つの結果に単純に減らすために使用されます。他の言語のinject
ように知っているかもしれません。はRubyの のエイリアスです。のより簡単な例を次に示します。reduce
reduce
inject
inject
[1,2,3,4].inject(0) do |sum, number|
sum + number
end
# => 10
0 はアキュムレータ - 初期値です。ペア|sum, number|
でsum
は、 がアキュムレータになりnumber
、配列内の各数値が次々になります。inject
0 に 1 を加算しsum
、次のラウンドのために結果をsum
に格納し、 に 2 を加算し、結果を にsum
再度格納するなどです。アキュムレータの単一の最終値がsum
戻り値になります。ここで 10. あなたの例で追加された複雑さは、アキュムレータがブロック内の値とは種類が異なることです。それはあまり一般的ではありませんが、悪いことでも偏ったことでもありません。(編集: Andrew Marshall は、おそらくそれは悪いことであると指摘しています。元の質問に対する彼のコメントを参照してください。また、@tokland は、inject
here は map の非常に複雑な代替手段にすぎないと指摘しています。は悪いです。) の例については、質問へのコメントでリンクした記事を参照してくださいinject
。
編集: @tokland がいくつかのコメントで指摘しているように、コードには簡単なmap
. その場合、はるかに簡単に読むことができます。
def differences(before, after)
before.diff(after).keys.sort.map do |k|
{ :attribute => k, :before => before[k], :after => after[k] }
end
end
コードが何をしているかを説明することに集中しすぎていました。単純化する方法すら考えていませんでした。