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_for
やlink_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]
に変更するなど)。
参考文献