【Rails】form_withについて(ネスト)
はじめに
ルーティングがネストしている時の、form-withの書き方を備忘録として残しておきます。
ルーティング(ネスト)
resources :boards do resources :comments end
createアクション
ネストしたモデルのコメントをcreateするとき 、
/boards/:board_id/comments
上記の、URLにPOSTリクエストを投げないといけません。 コメントは必ずいずれかの掲示板に紐づいているので、どの掲示板のコメントなのかという情報が必要になります。 ですので@board = Board.find(params[:board_id])でコメントする掲示板を取得しています。 したがって、コントローラーでは、ビューのフォームに必要なboardの情報とcommentの情報を送れるよう下記の設定を行います。
def new @board = Board.find(params[:baord_id]) @comment = Comment.new end
これを元に、ビュー側は下記のように引数に配列を渡す形になります。
<%= form_with model: [@board, @comment] do |form| %> # または<%= form_with model: comment , url: [board, comment] do |form| %> <%= form.text_field :text %> <%= form.submit %> <% end %>
# create時のhtml <form action="/boards/1/comments" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="硖" />
@commentが空っぽということからform_withでは、createアクションを呼ぶためのURLをコントローラでもらったidを元に生成することができます。
/boards/:board_id/comments
updateアクション
commentをupdateするときは、
/boards/:board_id/comments/:id
上記の、URLにPOSTリクエストを投げないといけません。 ここでも、コントローラーでは、ビューのフォームに必要なboardの情報とcommentの情報を送れるよう下記の設定を行います。
def edit @board = Board.find(params[:board_id]) @comment = Comment.find(params[:id]) end
ビューでのフォームはパーシャルで同じものを使用します。
<%= form_with model: [@board, @comment] do |form| %> # または<%= form_with model: comment , url: [board, comment] do |form| %> <%= form.text_field :text %> <%= form.submit %> <% end %>
# update時のhtml <form action="/boards/1/comments/1" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="_method" value="patch" />
createの時と違いことは、@commentのデータがすでにあるということです。よって、form_withはupdateアクションを作るためのURLを作ってくれます。
/boards/:board_id/comments/:id
このURLに必要なidをコントローラで取得し、このURLでPOSTリクエストをしています。
同じフォーム(部分テンプレート)で、createとupdateを使い分けています。