Rails: ハッシュのマージをwith_defaultsメソッドで明快に書こう(翻訳)
Railsは、可読性を高めるためにActive Supportで既存のコアRubyクラスに多くのメソッドを追加することで知られています。Hash
クラスのwith_defaults
メソッドもその1つです。with_defaults
メソッドは、別途追加済みのreverse_merge
メソッドのエイリアスなので、この名前が動作を知る手がかりとなるはずです。
reverse_merge
メソッドのソースコードを見るとわかるように、実装は実に簡素です。
🔗 以下のように書くよりも
デフォルト値をHash#merge
で追加する。
user_provided = {q: "Andy", age: 44, limit: 1}
listing_options = {order: "asc", limit: 25}.merge(user_provided)
#=> {:order=>"asc", :limit=>1, :q=>"Andy", :age=>44}
🔗 以下のように書こう
#with_defaults
メソッドを利用する。
user_provided = {q: "Andy", age: 44, limit: 1}
listing_options = user_provided.with_defaults(order: "asc", limit: 25)
#=> {:order=>"asc", :limit=>1, :q=>"Andy", :age=>44}
🔗 そうする理由
この「シンプルな」メソッドが存在する理由は、Webアプリケーションでは、メソッドに渡したコンフィグやオプション引数を処理する機会が多いためです。
with_defaults
を使う方が、Rubyのmerge
を使うよりも可読性が高まります。メソッドの意図がwith_defaults
という名前ではっきりわかるので、コードも理解しやすくなり、メンテも容易です。
Railsには、このような形で構文が改善された例が数多くあります。最初のプルリク(#28603)でwith_defaults
エイリアスを追加する根拠となったのは、コードが「Railsらしく書ける」からです。
with_defaults
メソッドで書けば、マージで元のハッシュ値が優先され、該当する値がない場合は優先順位の低いデフォルト値が使われることがメソッド名から明らかになります。
🔗 そうしない理由があるとすれば
RailsフレームワークがRubyのコアクラスに暗黙で「モンキーパッチ」を当てることに反対する人もいます。
しかしRailsのコードベースで作業する場合、フレームワークの実践的な決定(や好み)に逆らって実装すると、作業が面倒になる可能性もあります。
さらに、Railsで当てられた従来のパッチの中には、「Rubyらしい」という理由でRubyそのものに取り込まれたものもあります。このwith_defaults
のようなメソッドの構文や読みやすさは、確実にこのカテゴリに分類されるように感じられます。
概要
原著者の許諾を得て翻訳・公開いたします。