Kintarou'sBlog

プログラミング学習中。学習内容のアウトプットや読書で学んだことなど随時投稿!

【Rails】paramsまとめ

こんにちは😊Kintarouです。

現在エンジニア転職を目指してTECH CAMPにてプログラミング学習中です👨‍🎓
夢はフリーランスエンジニアになって働く人が働きやすいシステムを作ること!
と、愛する妻と海外移住すること🗽

プログラミングや読んでいる本のことなど、ブログに書いていきます!
twitter : https://twitter.com/ryosuke_angry


今日はRailsのparamsについてまとめていきます。
私の場合の事例で、resourcesでルーティングしてるにも関わらずform_withでmodel指定したパラメーターを送るとRouting Errorとなる時の解決策も記載しています。
【問題】と【原因】の項をご覧ください。

今回参考にさせて頂いたサイト🙇‍♂️

HTTP GETとPOSTの違い - ITを分かりやすく解説
[RESTful API]パスパラメータ、クエリパラメータ、リクエストボディの違いと設計 - Qiita
【Rails入門】params使い方まとめ | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト

前提

まず前提知識となる「パラメーター」からまとめます。

パラメーター

パラメーターとは、リクエストに含まれて送られるデータのことです。
リクエストに添えて送ることから「リクエストパラメーター」と呼ばれます。

リクエストパラメーターにはHTTPメソッドの違いにより
- GETパラメーター(URLパラメーター)
- POSTパラメーター
の2通りがあります。

GETパラメーター

URLにパラメーターを添えて送信します。URLに送信内容が見える状態になっており、サーバーからリソースを取り出すことが基本的な目的です。
特に、URL中の?の前にあるパラメータを「パスパラメーター」、?以降のパラメーターを「クエリパラメーター」と呼びます。

「パスパラメーター」「クエリパラメーター」の違い

パスパラメーターにはリソースを識別するために必要な情報を入れ、クエリパラメーターにはそのリソースを”操作して取得する”際に必要な情報を入れます。

https://example.com/groups/1?sort=false&limit=3

#上記の場合、group_id=1のリソース(パスパラメーター )を3件(limit=3)昇順でソート(sort=false)(クエリパラメーター)しています。

「パスパラメーター」「クエリパラメーター」の使い分け

上記の例の場合、group_id=1のリソースを取得したいのであれば

#パスパラメーター 
https://example.com/groups/1

#クエリパラメーター
https://example.com/groups/?id=1

となり、取得する情報に条件がない(一意)なのでパスパラメーター で取得する方が向いています。
逆に先の例のように一意でなく、sortやlimitで条件をつけた方がいいのであればクエリパラメーターが向いています。

POSTパラメーター

クライアントからWebサーバーに送信するためのパラメーターです。
こちらはURLに表記されることなくBody部に格納されるので、重要な情報や公開したくない情報を送る目的で使用します。

paramsメソッド

ではparamsとは何か。
paramsは、Railsでリクエストパラメータ(主にクエリパラメーターとPOSTパラメーター)を受け取るためのメソッドです。

基本的に

params[:パラメータ名]

で受け取ります。
過去記事でメンターの方に教わった部分がようやく理解できました笑
ryosuke-toyama.hatenablog.com

showアクションなどでテーブルから1つのレコードを取り出す際の

def show
  @hoge = Hoge.find(params[:id])
end

は例えばhttps://example.com/hoges/?id=1のid=1をparamsメソッドで受け取ったのでid=1のレコードをHogeテーブルから取り出してね。ということなのですね。

ストロングパラメータ

パラメーターを安全に受け取るための仕組み。
paramsでなんでもかんでも受け取ってしまうと、"仮に管理者権限trueとしてリクエストパラメータを送ってしまえば誰でも管理者になれてしまう"ことになります。

なので、受け取れるパラメータをrequire(:hoge)のpermit(:fuga)(hogeモデルのfugaカラムだけ受け取るよ)と制限してしまうという仕組みです。

【問題】requireをかけるとパラメーターが取得できなくなった!

私の場合の事例です。
createアクション時にrequireをかけるとRouting Errorとなり
No route matches [POST] "/tasks/new"というエラーコードが出てきてしまいました。

※この時ルーティングはresourcesで行っており、form_withの送信先はmodel:@taskとしておりました。

この時のエラー対策として、"requireの表記を消してpermitだけにすれば良いよ!"という記事がいくつかあったのでそうしたのですが、そうすると今度はupdateアクションが正しく実行されないという事態になりました。

この場合はrequire(:task)の表記があれば正しく更新されます。

【原因】newアクション時にインスタンスを生成していなかった!

この時ストロングパラメーター

def task_params
  params.require(:task).permit(:runtime, :place, :todo)
end

という表記により、params[:task][:runtime]、params[:task][:place]、params[:task][:todo]のパラメーターを受け取りたかったのが

def new
end

としていたことにより、newのビューには@taskの情報が行っておらずform_withで指定された@taskはどこの何?=Routing Error となっていたんですね。

本来は

def new
  @task = Task.new
end

とすべきでした。

※editアクションには@task = Task.find(params[:id])でしっかりインスタンスを生成する表記があり、updateアクションも成功していたんですね。

以上、どなたかの参考になれば幸いです😊