【Rails】俺はform_withと分かち合いたい

form_with is 何?

form_withとは、railsで情報を送信するためのヘルパーメソッドです。 form_withを使うことにより、簡単に入力フォームに必要なHTMLを作成することができます。

引用元:form_withの使い方を徹底解説!

特定のコントローラーで任意のデータを受け取りたい(urlオプションの指定)

特定の画面のフォームから送られてきた値を任意のコントローラーで利用したい場合は以下のようにurlオプションを指定してコントローラーを指定して、必要ならmethodオプションを指定してHTTPメソッド(=アクション)を指定できる。

<%= form_with url: users_path, method: :get do |form| %>
  <!--フォーム内容 -->
<% end %>

生成されるHTML

<form action=”/users” method=”get”>
・・・
</form>

送られてきたデータをDBに保存して永続化したい(modelオプションの指定)

フォームから送られてきたparamsをDBに保存したい場合は、保存したい対象のモデルをmodelおオプションに指定する。methodオプションは指定がなかった場合POSTがデフォルトのHTTPメソッドとして選択される。

<%= form_with model: User.new do |form| %>
  <%= form.text_field :name %>
  <%= form.number_field :age %>
  <%= form.submit %>
<% end %>

生成されるHTML

<form action=”/users” method=”post”>
	<input type="text" name="user[name]" id="user[name]">
	<input type="number" name="user[age]" id="user[age]">
	<input type="submit" name="commit" value="保存する" data-disable-with="保存する"> 
</form>

渡ってくるparams

params
=> <ActionController::Parameters {
  "utf8"=>"✓", 
  "authenticity_token"=>"<token>", 
  "user"=>{"name"=>"garasi", "age"=>"29"}, 
  "commit"=>"送信", 
  "controller"=>"users", 
  "action"=>"create"
} permitted: false>

modelオプションが指定されている場合のデフォルトの挙動

  1. 該当のモデルオブジェクトから特定したcontroller・アクションに対するpostリクエストの送信
  2. 渡されたインスタンスが空ならPOST, IDを持っていればPATCHがHTTPメソッドとして指定される(methodオプションで任意のHTTPメソッドを指定もできる)
  3. ActiveRecordと連携してモデル名とモデルの属性名をinputのname属性に付与する

Rails 5.1以前のformヘルパー

form_tag(DBへの永続化が不要な場合に利用)

form_tagはフォームに入力されたデータを保存する必要がない時に使われます。

引用元:form_tagの使い方を習得しよう

<%= form_tag('/main', method: :post) do %> 
  <input type="text" name="nickname"> 
  <input type="submit"> 
<% end %>

form_for(DBへの永続化を行う場合に利用)

それに対し入力されたデータを保存する必要があるときはform_forを利用します。

form_forの使い方をマスターしよう!

<%= form_for(@user) do |f| %>
  <%= f.text_field :name %>
  <%= f.submit %>
<% end %>
  • form_forではFormBuilderオブジェクトのヘルパーメソッドを使用できる
  • modelとurlの指定により用途の使い分けを可能にし、書き方を統一したのがform_with
  • Rails5.1以降のアプリケーションでは基本的にform_withで書くのが一般的
  • 昔のプロダクトでform_tag, form_forを利用している箇所があった場合に、出力されるhtmlがイメージできる程度にはなっておく必要がある

ネストしたモデルへの指定

ルーティングでネストを定義している時は記述が変わる。
記事に関するコメントを投稿するフォームを例にあげてみる。まずはコントローラーのインタンス変数の定義。

def new
  @article = Article.find(params[:article_id])
  @comment = Comment.new
end

def edit
  @article = Article.find(params[:article_id])
  @comment = Comment.find(params[:id])
end

コメントは必ずいずれかの記事に紐づいているので、どの記事のコメントなのかという情報が必要となる。
そのため@article = Article.find(params[:article_id])でコメントする記事を取得。ビュー側は下記のように引数に配列を渡す形式となる。

<%= form_with model: [@article, @comment] do |form| %>
  <%= form.text_field :text %>
  <%= form.submit %>
<% end %>

参考記事

form_with | Railsドキュメント
form_withの使い方を徹底解説!