はじめに
こんにちは、23日目のカレンダーを担当する@sleepy_catです。
今現在メンターをしていますがこの質問かなり多いなと感じ、また、Railsを学び始めた頃にちょくちょく見かけて理解するのが大変だったparamsについての記事を書いていきます。
この記事を読んで欲しい方
- モデル.find(params[:id])ってとりあえずshowアクションに書いてるけどよくわからんって方
- formから送られてきたデータがよくわかんないけど直接DBに保存されると思ってる方
環境
$ rails -v
Rails 5.2.4.3
$ ruby -v
ruby 2.6.2p47 (2019-03-13 revision 67232) [x86_64-linux]
Rails5系です。現在6系が最新ですが、バージョンそこまで関係ない話だと思います。
paramsとは
クライアントからURLやフォームで送信された値(パラメータ)を取得するメソッドです。
これでわかりましたって方は多分元からこの記事を読んでないはずなので詳しく見ていきましょう。
パラメータの送り方について知る
ここでいうパラメータとはユーザ側のアクションによってページ遷移の時に一緒に送られるデータ(リクエスト情報)のことをいいます。主に送り方は3種類あります。
注)このパラメータについて知るにはHTTPメソッドやformについての知識も必要ですがそれも書くとめんどくさいかなり長くなってしまうため割愛させていただきます。
クエリパラメータ
URLパラメータとかクエリ文字列とか正しい呼び方がわからない...
遷移先がGETメソッドの時のデータの送り方。データの送り方としてはシンプルでURLの末に送りたいデータを載せて送るやり方です。
例を出すなら
https://hogehoge/hugahuga/index?like=dog
このURLの?以降がクエリパラメータです。今回はlikeという名前のデータを送っていますね(データの中身はdog)。一つしか送れないかというとそんなことはなくいくつも送れます。
よく見る場面としては検索機能ではこのクエリを用いてデータがやり取りされることが多いです。実際にこのqiitaの検索機能を使って検索結果のページに飛んだ後、URLを確認してみましょう。URLにクエリパラメータがあるのが確認できると思います。
もう一つよく使われる場面としてはWebサイトのアクセス解析をするために付けられることがあります。一番イメージしやすいのが個人ブログに貼ってあるamazonとかへのリンクだと思います(俗にいうアフィリエイト)。あのリンクはそのブログ経由で商品が購入された時にブログ主にも収益が入ると言った物ですが、じゃあどのサイトからきたのか、というのを示すためにクエリがついていることがあります。
ルートパラメータ
先ほどのクエリがURLの末にデータを載せるやり方ならこちらはURLの中にパラメータを入れ込むやり方です(URLの一部をパラメータと見なす、の方が適切かもしれませんが)。
例として以下のルーティングがあるとします。
Rails.application.routes.draw do
resources :users
end
Prefix Verb URI Pattern Controller#Action
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show <=この行を主に考えます
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
ここで一部ルーティングのURL(URI Pattern)に少しおかしな物が紛れているかと思います。"/:id"といった部分です。まさしくこの部分がパラメータとなる部分です。このようにURLの文字列内にコロンがついた部分は文字として扱われず一種の変数として扱われます。
(前提条件 Railsが動く順番として
URLが入力される => ルーティングで一致するcontroller/actionが実行)
例えば/users/1
というURLのページを開こうとするとこれに一致するルーティングは/users/:id(.:format)
だとRailsは判断します。"id"という名前のデータ(中身は1)が渡されページ遷移が行われるといったイメージです。
おまけ
Prefix Verb URI Pattern Controller#Action
item GET /qiita.com/:user_name/items/:item_id(.:format) items#show
こんなパスがあるとして
https://qiita.com/sleepy_cat/items/c8eecfc5c486b0f7f2b8
このサイトを開きたいと思います。ここで得られるパラメータは何があるでしょうか
答え
①`user_name`という名前のデータ、中身は`sleepy_cat` ②`item_id`というデータ、中身は`c8eecfc5c486b0f7f2b8`ポストデータ
遷移先がPOSTの時のデータの送り方。ログインの時などにフォームにメールアドレスやパスワードを入力して画面遷移など一番イメージしやすいと思います。通常ユーザ側が送られたデータを確認することはできないので(クエリなどはURL確認すると一発でわかってしまいますよね)セキュリティ上今までのものと比べ一番ましです。
paramsとは(再び
さて、データの送り方がいくつかあることはわかった。じゃあ受け取り方は?とここまで読んでいただいた方は思っている頃だと思います。それこそがparamsメソッドです。Railsではこの三つのデータを1つにまとめてparams[:パラメータ名]
といった形で受け取れるようになっています。
ではこんなルーティングがあり
Prefix Verb URI Pattern Controller#Action
user GET /users/:id(.:format) users#show
/users/4
とURLが指定され、コントローラで
def show
@user = User.find(params[:id])
end
と記述されていたら、@user
にはどんなプロセスで、どんな値が入っているのか、今ならわかるはずです。
①まずURLパラメータとして、このページに"id"という名前のデータが送られます。
②送られた"id"というデータをparams[:id]
が受け取ります。
③受け取ったデータの中身は"4"なので@user = User.find(4)
となる。
④Userモデルからfindメソッドでidが4のデータを持ってきて、@user
に入力されます。
確かめてみよう
paramsで受け取れるデータはどこで受け取ればいいのか。確認方法としてはデバッグ用gemで見たりもいいですが、ターミナルを確認してみるのもいいでしょう。
こちら一部変更してますが簡単に作ったアプリケーションでupdateアクションを行った時のターミナルの一部です。
Started POST "/users/2" for 999.999.999.99 at 2020-12-23 09:25:51 +0000
Cannot render console from 999.999.999.99! Allowed networks: 127.0.0.1,
::1, 127.0.0.0/127.255.255.255
Processing by UsersController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ABw1gqVMw8Jhogehogehugahuga",
"user"=>{"name"=>"sleepy_cat", "text"=>"i love dog"}, "commit"=>"Update User",
"id"=>"2"}
.
.
.
注目していただきたいのが"parameters:"から始まる記述の部分です。{"データの名前" => "データの中身","データの名前" => "データの中身"...}となっています。
例えばここでparams[:id]
とすると得られるデータは"2"
です。またparametersはハッシュのデータもあり、"user"=>{"name"=>"sleepy_cat", "text"=>"i love dog"}
この部分は入れ子のようになっているため取り出す際はparams[:user][:name]
とすると"sleepy_cat"
が得られます。
まとめ
ちなみにparamsメソッドはcontrollerとviewで扱うことができます。
Railsの場合、formだろうとクエリだろうと①ページ遷移②parametersに情報集まる③コントローラなどで使う、モデルに振り分ける(ストロングパラメータなどがここに密接に関わってくるのでよかったら更に調べてみてください)等をするといった手順さえ頭の中に描けていればよりRailsの記述の理解が進むかもしれません。
この記事を読んでparamsと少しは仲良くなれそうだと思っていただけたら幸いです。