Ruby on Rails

【Rails】ハッシュからの値取り出しは、paramsからの値取り出しと少し違う

バートリーのさいとうです。

今回は

【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本を目標に、実務から学んだプログラミングのあれこれを発信しています。

誰かのためになれば、嬉しいです。

最後まで読んでいただき、ありがとうございました。

それでは。

参考記事

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA