コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

Railsで with_indifferent_access を使うときは一呼吸おいて考えて欲しい

ただのコラム

(この話を題材にする)環境

$ bin/rails -v
Rails 5.2.2

with_indifferent_accessというメソッド

Hashの拡張機能としてAvtiveSupportが用意しているメソッド

rails/hash_with_indifferent_access.rb at master · rails/rails · GitHub

Hashのキー値をsymbolでも文字列でも取得可能にするもの。

hash = { a: "A", "b" => "B" , c: "C"}
convert_hash = hash.with_indifferent_access

# symbolで設定したものでも、文字列でも取得ができる
pp convert_hash["a"]
"A" 
pp convert_hash[:b]
"B"

従来使う際に考えてほしいこと

このメソッドを通したほうが、 convert_hash["a"] でも convert_hash[:a] でも 取れるので一見便利だが普通のコードを書く場合は悩ましい部分ができる。

  1. このハッシュに内容をセットする側はsymbolで設定すべきか、文字列で設定すべきか悩んでしまう。
  2. 取り出す際もsymbolと文字列でどっちつかずになる可能性がある
  3. 戻り値などでハッシュを渡すときにどっちで使われるかわからないからwith_indifferent_accessの形式にしておきたい

という観点がある。

しかしながら1,2の観点はスコープ内でどっちの形式かに寄せてしまえばいいので deep_symbolize_keys もしくは deep_stringify_keys を使ってどちらかに全て変えてしまえばいい

そうなると、このメソッドを使う理由は3の視点だけとなるが、こちらも戻り値の形式が symbolキー値としてはHash、または文字列キー値としてのHashとして変えてしまえばいいので、どう使われて欲しいかが決まれば自ずとキーのタイプも決まる。

こう考えていくと with_indifferent_access が強く切望されるケースは少なめなため、deep_xxxx_key で揃えるほうが処理実態もその変換後の受け取る側もシンプルに考えることができるため、「その with_indifferent_access はなんでしたいのか」を考えたほうが良さそうかと思った。

参考サイト