【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="&#x7856;" />

@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="&#x2713;" /><input type="hidden" name="_method" value="patch" />

createの時と違いことは、@commentのデータがすでにあるということです。よって、form_withはupdateアクションを作るためのURLを作ってくれます。

/boards/:board_id/comments/:id 

このURLに必要なidをコントローラで取得し、このURLでPOSTリクエストをしています。

同じフォーム(部分テンプレート)で、createとupdateを使い分けています。