はじめに
こんにちは!hinata です!
Railsで開発していると、こんな経験ありませんか?
- フォームは作れたのに、
paramsが想定と違う形で届く -
params[:user][:name]だと思ったらnilになる -
form_withのmodel / url / scopeの違いがよく分からない - そもそも paramsって何者? という気持ちになる
正直に言うと、自分は form_with と params の理解がかなり曖昧でした。
そこでこの記事では、
-
paramsはそもそもどこから来るのか - どんなルールで送られてくるのか
-
form_withの指定によって params がどう変わるのか
を、具体的なコード例ベースで整理します。
⚠️ 注意
本記事の内容は、Rails初学者である筆者が
実際に開発中につまずいたポイントと、その時点での理解をもとにまとめたものです。設計や実装については、より良い書き方・考え方が存在する可能性がありますが、
「初学者がどう悩み、どう整理したか」という観点で読んでいただけると嬉しいです。
そもそも params とは何か?
params は、ブラウザからサーバーに送られてきたデータをまとめたものです。
Railsでは、以下の情報がすべて params に入っています。
- フォームで入力された値
- URLのクエリパラメータ(
?q=railsなど) - ルーティングで指定された
:id
例:URLに含まれる params
/users/10?active=true
params
# {
# "id" => "10",
# "active" => "true"
# }
👉 params の中身はすべて文字列(String)
フォームから送られるデータの正体
HTMLフォームでは、すべての入力値は次の形で送信されます。
name=value
Railsは、この name をもとに params を組み立てています。
name と params の対応関係
フラットな例
<input name="q" value="rails">
params[:q]
# => "rails"
ネストする例(角括弧)
<input name="user[name]" value="太郎">
params[:user][:name]
# => "太郎"
さらにネストする例
<input name="search[conditions][keyword]" value="rails">
params
# {
# "search" => {
# "conditions" => {
# "keyword" => "rails"
# }
# }
# }
params[:search][:conditions][:keyword]
# => "rails"
👉 角括弧 [] が Hash のネスト構造になる
ここまでが Rails以前の前提知識 です。
form_with は何をしているのか?
ここでようやく Rails の話に戻ります。
form_with は、params を直接操作していません。
やっていることはシンプルで、
input の name を Rails流に自動生成しているだけ
です。
つまり、
- model を渡す
- scope を指定する
- 何も指定しない
これらの違いはすべて
**「どんな name を生成するか」**の違いです。
form_with × params パターン集
ここからは、name がどう作られ、params がどうなるかだけに注目します。
パターンA:model を渡す(CRUDで最頻出)
<%= form_with model: @user do |f| %>
<%= f.text_field :name %>
<% end %>
生成される name:
user[name]
params:
params[:user][:name]
👉 model名がそのまま params のキーになる
パターンB:url のみ(scopeなし)
<%= form_with url: search_users_path, method: :get do |f| %>
<%= f.text_field :q %>
<% end %>
生成される name:
q
params:
params[:q]
👉 f を使っていても、scope がなければネストされない
パターンC:scope を指定する
<%= form_with url: search_users_path, method: :get, scope: :search do |f| %>
<%= f.text_field :q %>
<% end %>
生成される name:
search[q]
params:
params[:search][:q]
👉 scope は params のルートキーを作る
パターンD:scope を user にする
<%= form_with url: users_path, scope: :user do |f| %>
<%= f.text_field :name %>
<% end %>
params:
params[:user][:name]
👉 model がなくても、modelっぽい params を作れる
パターンE:text_field_tag で name を直指定する
<%= form_with url: search_users_path, method: :get do %>
<%= text_field_tag "user[name]" %>
<%= submit_tag "検索" %>
<% end %>
params:
params[:user][:name]
👉 params を完全にコントロールしたいときの最終手段
チートシート(ここだけ見ればOK)
| form_with | input | params |
|---|---|---|
model: @user |
f.text_field :name |
params[:user][:name] |
url: |
f.text_field :q |
params[:q] |
url + scope: :search |
f.text_field :q |
params[:search][:q] |
| なんでも | text_field_tag "user[name]" |
params[:user][:name] |
よくある勘違い
method: :get は params が違う?
→ 違いません。
URLに表示されるだけで、controller では同じ params です。
Turbo が原因?
→ params の形自体は変わりません。
Strong Parameters のせい?
→ それは「取り出し方」の話で、
params がどう作られるかとは別の話です。
まとめ
- params は ブラウザから送られてきたデータの集合
- params の形は input の name で決まる
- form_with は name を自動生成してくれるだけ
- 迷ったら HTMLを見て name を確認する
form_with の挙動が分かると、
検索フォームや複雑な条件フォームも一気に書きやすくなります。
同じところで詰まっている人の助けになれば嬉しいです 🙌
開発したアプリ「FES READY」でもたくさん今回の記事の技術を使用しているので、
よければ触ってみてください!

🔗 FES READY
- アプリURL:https://fesready.com
- GitHub:https://github.com/hinata7777/fes_ready