form_withの使い方をまとめてみた

form_withってただフォームの作成に使うためのメソッドなんでしょ。という認識で終わっているので、今後の自分のためにも基本的なところをまとめてみました。

基本概念

<%= form_with model: @user, url: login_path, local: true do |f| %>

・form_withの後には次のパスに送るもの、送る先を記載する

・form_withがControllerに送るとき、HTTPステータスはデフォルトでPOSTになる。つまりcreateアクションに遷移するフォームが生成される。

form_withで値を送信するときの分類

モデルを渡したときは、URLとスコープaが自動推測されます。(これまでのform_for と同じ。) URL: @userがDBに存在するときは、updateアクションに、ないときは、createアクションに飛びます。

同じコントローラーのアクション内でしか送ることが出来ないので、別のコントローラーに送信したいときは下記のようにurlを指定する必要があるようです。

<%= form_with url: root_path do |form| %>
  フォーム内容
<% end %>

これは、form_tagのように入力された情報をデータベースに保存しない時の記述方法になる。

ビューファイル | form_withの書き方

コメントを作成される場合、どのモデルに紐づいているのかをmodel: の後に記載することで指定することが出来る。


<%= form_with model: モデルクラスのインスタンス do |form| %>
  フォーム内容
<% end %>
こちらはデータベースに保存する時の記述になる。

コメントは必ずいずれかの記事に紐づいているので、どの記事のコメントなのかという情報が必要になります。

ですので

@article = Article.find(params[:article_id])

でコメントする記事を取得しています。

Viewファイルでフォームを作るとこうなる
<%= form_with model: [@article, @comment] do |form| %>
  <%= form.text_field :text %>
  <%= form.submit %>
<% end %>

コントローラーで@foodが設定されて、nameがハンバーグだった場合、下記コードは

<%= text_field(:person, :name) %>

このとき、上のコードからは以下の出力が得られます。

<input id="food_name" name="food[name]" type="text" value="ハンバーグ"/>

このフォームを送信すると、ユーザーが入力した値はparams[:food][:name]に保存されます。params[:food]ハッシュはFood.newに渡しやすくなっています。@foodがFoodモデルのインスタンスであれば@food.updateにも渡しやすくなっています。これらのヘルパーでは2番目のパラメータとして属性名を渡すことがほとんどですが、必ずしもそうでないヘルパーもあります。上の例で言うなら、foodオブジェクトにnameメソッドとname=メソッドがありさえすればRailsは余分な作業をせずに済みます。

<%= form_with model: @post do |form| %>
  ...

<% end %>

上記コードは以下の通りになる。

<%= form_with scope: :post, url: post_path(@post), method: :patch do |form| %>
  ...
<% end %>

form_withで使えるオプション

:url

フォームの送信先URLを指定します。渡せる値は、url_forlink_toで渡せる値と似ています。たとえば、名前付きルートを直接渡すこともできますし、:urlなしで:scopeを渡すと、現在のURLにフォームを送信することもできます。

:method

フォーム送信時のHTTPメソッド(verb)を指定します。通常は:get:postを指定します。:patch:put:deleteを指定すると、隠しinput名の後ろに_methodが追加され、POST verb上でこれらのHTTP verbをシミュレートします。

:scope

inputフィールド名のプレフィックスにスコープを追加します。これにより、送信されたパラメータをコントローラでグループ化できます。

:namespace

フォームの要素でid属性を一意にする名前空間です。namespace属性で指定した名前にアンダースコアを追加したものが、生成されたHTML idの前に追加されます。

:model

:url:scopeの自動推測に使うモデルオブジェクトを指定し、inputフィールドにモデルの値を表示します。たとえば、title属性の値が"Ahoy!"ならtitleの入力フィールドの値に"Ahoy"と表示されます。モデルが新しいレコードの場合は作成用フォームが生成され、モデルが既存のレコードの場合は更新用フォームが生成されます。デフォルトの動作を上書きするには、:scope:urlを渡します(params[:post]params[:article]に変更するなど)。

参考文献


form_withの使い方を徹底解説!

form_with | Railsドキュメント