バートリーのさいとうです。
今回は
【Rails】ハッシュからの値取り出しは、paramsからの値取り出しと少し違う
というテーマで、僕が実務から得られた学びを共有したいと思います。
Rubyには、ご存知の通りHash(ハッシュ)というものが存在します。
一方で、RubyではなくRailsには、paramsというものも存在します。
これは、ViewからデータがControllerに送られる際に、Viewで入力された値を格納し、Controllerに送る責務を持つものです。
この両方に共通するのは、以下のような記述の仕方がされることです。
author= {
"id" => "1",
"name" => "saito",
"age" => "24",
"gender" => "male",
}
p author["name"]
#出力結果: "saito"
この同じ記述を行うハッシュとparams、実際に値を取得する際に、少し沼ったので
- 何に沼ったのか
- その原因とは?
を解説することを通して
- ハッシュとparamsでは、値が取得できる方法への制限が異なる
- その違いが生まれる理由
- railsでは、パラメーターを確認することで沼から抜けられる
以上3つのトピックを解説していきます。
ハッシュは本当に使う機会が多いので、この記事を通して純粋なハッシュとparamsの違いを理解すれば、実装の幅も広がると思いますので、最後までお付き合いください。
ハッシュとparamsでは、値が取得できる方法への制限が異なる
では早速本題に入ります。
ハッシュもparamsも、キーを指定して値(バリュー)を取得するのは同じです。これはキーバリューストアと呼ばれます。
しかし、そのキーを指定する方法に少しひっかけがあります。
paramsの場合
ではまず、Railsを触った方なら一度は必ず出会ったことがあるparamsから。
以下のようにparamsのキーは指定できます。
#シンボルを指定
user = User.find(params[:id])
#文字列を指定
user = User.find(params["id"])
どちらでも取得することができます。
このとき、paramsの中身は例えばこんな感じです。
Parameters:
{
"utf8"=>"✓",
"user" =>
{
"name" => "saito",
"age" => "24",
"gender" => "male"
},
"id" => "1",
"commit" => "決定する"
}
文字列 => 文字列の関係ですが、paramsキーに指定できるのは文字列とシンボルです。
ハッシュの場合
対して、ハッシュの場合は、どうでしょうか。
まずは、先ほどの同じ内容を取得するハッシュを作成します。
user = {
"id" => "1",
"name" => "saito",
"age" => "24",
"gender" => "male",
}
先ほどと同じ方法で取得してみましょう。
#シンボルを指定
p user[:id]
# => nil
#文字列を指定
p user["id"]
# => "1"
文字列ではvalueを取得できましたが、シンボルでは取得できませんでした。
これは、
・ハッシュのキーが文字列で定義されていれば文字列
・シンボルであればシンボル
で指定する必要があることを定義しているためです。
paramsでは文字列でキーが定義されていても、両方でキーを指定することができたので、混乱しますね。
では、この違いはなぜ生まれるんでしょうか?
ハッシュとparamsは、異なるクラスから生成されている。
こちらの記事を参考にすると、
params
って文字列でもシンボルでも value を取り出せますよね。あれの型は実は Hash ではなくて Hash のサブクラスである ActiveSupport::HashWithIndifferentAccess なんです!
とあります。実際にparamsが生成されているActiveSupport::HashWithIndifferentAccessクラスのドキュメントを見てみると
Implements a hash where keys :foo
and "foo"
are considered to be the same.
= 「:fooと”foo”は同じように扱われるで!」
と言ってます。これがparamsではキーをどちらでも許可している理由ですね。
ハッシュで両方許可するためには
ハッシュでも、paramsのようにキー指定できたら楽ですよね
そのときは、以下のようにwith_indifferent_accessをハッシュに付与することができます。
user = { "id" => "1", "name" => "saito", "age" => "24", "gender" => "male"}.with_indifferent_access
p user[:id]
# => "1"
p user["id"]
# => "1"
こうすることで、両方取得することができます。
まとめ
今回は、【Rails】ハッシュからの値取り出しは、paramsからの値取り出しと少し違う、というテーマで解説してきました。
これがsidekiqで起きていたので、余計沼っていました。
このブログは、月に15本を目標に、実務から学んだプログラミングのあれこれを発信しています。
誰かのためになれば、嬉しいです。
最後まで読んでいただき、ありがとうございました。
それでは。
参考記事