目的
form_withについて知る
(前提、環境)
mac
macOS Mojave 10.14.5
ruby 2.5.1
rails 5.2.3
はじめに
公式
Ruby on Rails 5.1.7 ModuleActionView::Helpers::FormHelper
https://api.rubyonrails.org/v5.1.7/classes/ActionView/Helpers/FormHelper.html
参考記事
Ruby on Rails 5.1 リリースノート
https://railsguides.jp/5_1_release_notes.html#form-for%E3%81%A8form-tag%E3%81%AEform-with%E3%81%B8%E3%81%AE%E7%B5%B1%E5%90%88Rails 5.1〜: ‘form_with’ APIドキュメント完全翻訳
https://techracho.bpsinc.jp/hachi8833/2017_05_01/39502
form_withとは
formタグを自動生成してくれるヘルパーメソッドです。
Rails5.1になって「form_for」と「form_tag」を統合したもの。
※Rails5.1以前の「form_for」や「form_tag」は非推奨になりました。。。
form_withの使い方
抽象的な書き方
form_withメソッドの書き方です。
Rubyだと()を半角スペースで省略できます。
form_with(model: nil, scope: nil, url: nil, format: nil, **options)
具体的な書き方
UTF-8サポート用に自動生成される隠しフィールドや、CSRF(クロスサイト・スクリプト・フォージェリ)攻撃からの保護のために自動追加される認証トークンは都度生成されるたびに変わるので省略します!
よく見る書き方
コントローラーで@postを定義した前提であれば、下記のように記述がされているでしょう!
<%= form_with model: @post do |form| %>
<%= form.text_field :title %>
<%= form.submit value:"submit" %>
<% end %>
# =>
<form action="/posts" method="post" data-remote="true">
<input type="text" name="title">
<input type="submit" value="submit">
</form>
こちらをなんとなく使用しないために細かくオプションをみていこうと思います。
urlだけを指定した書き方
こちらだとinputタグのname属性にそのまま"title"がついています。
<%= form_with url: posts_path do |form| %>
<%= form.text_field :title %>
<%= form.submit value:"submit" %>
<% end %>
# =>
<form action="/posts" method="post" data-remote="true">
<input type="text" name="title">
<input type="submit" value="submit">
</form>
inputフィールド名にスコープのプレフィックスを追加する
こちらだとinputタグのname属性は"post[:title]"となります。
これはスコープオプションを追加して、postの中にどんどん入れるという指示を出すからですね!
<%= form_with scope: :post, url: posts_path do |form| %>
<%= form.text_field :title %>
<%= form.submit value:"submit" %>
<% end %>
# =>
<form action="/posts" method="post" data-remote="true">
<input type="text" name="post[title]">
<input type="submit" value="submit">
</form>
モデル(新規)を渡してURLとスコープを自動推測させる。
こちらが一番よく見る形の本当の姿①ですね!
form_forと同じように引数にモデルを渡してあげる形です。
<%= form_with model: Post.new do |form| %>
<%= form.text_field :title %>
<%= form.submit value:"submit" %>
<% end %>
# =>
<form action="/posts" method="post" data-remote="true">
<input type="text" name="post[title]">
<input type="submit" value="submit">
</form>
モデル(既出)を渡してURLとスコープを自動推測させる。
こちらが一番よく見る形の本当の姿②ですね!
既存のモデルの場合は更新用フォームが生成されます。
下記で自動生成されるinputタグのvalueが"patch"になっています。
<%= form_with model: Post.first do |form| %>
<%= form.text_field :title %>
<%= form.submit value:"submit" %>
<% end %>
# =>
<form action="/posts/1" method="post" data-remote="true">
<input type="hidden" name="_method" value="patch">
<input type="text" name="post[title]" value="<postのtitle>">
<input type="submit" value="submit">
</form>
ルーティングを名前空間を使っている場合
ルーティングをadmin_post_urlのように名前空間化する場合は以下のようにモデルのバリューを配列にして下記のように記述する必要があります!
<%= form_with(model: [ :admin, @post ]) do |form| %>
...
<%= form.submit value:"submit" %>
<% 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をシミュレートします。 |
:format | フォーム送信先であるルーティングのフォーマットを指定します。 :jsonなど通常と異なるリソースタイプを送信するのに便利です。 :urlがオプションに渡されている場合、このオプションはスキップされます。 |
:scope | inputフィールド名のプレフィックスにスコープを追加します。 これにより、送信されたパラメータをコントローラでグループ化できます。 |
:namespace | フォームの要素でid属性を一意にする名前空間です。 namespace属性で指定した名前にアンダースコアを追加したものが、生成されたHTML idの前に追加されます。 |
:model | :urlや:scopeの自動推測に使うモデルオブジェクトを指定し、inputフィールドにモデルの値を表示します。 たとえば、title属性の値が"Ahoy!"ならtitleの入力フィールドの値に"Ahoy"と表示されます。 モデルが新しいレコードの場合は作成用フォームが生成され、モデルが既存のレコードの場合は更新用フォームが生成されます。 デフォルトの動作を上書きするには、:scopeか:urlを渡します(params[:post]をparams[:article]に変更するなど)。 |
:authenticity_token | フォームで使う認証トークンを指定します。 カスタムの認証トークンを指定して上書きすることも、falseを渡して認証トークンのフィールドをスキップすることもできます。 有効なフィールドのみに制限されている支払用ゲートウェイへのような外部リソースにフォームを送信する場合に便利です 。config.action_view.embed_authenticity_token_in_remote_forms = falseを指定すると、埋め込み認証トークンがリモートフォームで省略されることがあります。 この指定はフォームでフラグメントキャッシュを使う場合に便利です。 (リモートフォームがmetaタグから認証トークンを取得するようになるので、JavaScriptがオフになっているブラウザをサポートする場合を除けば認証トークンをフォームに埋め込む必要がなくなります。) |
:local | local: trueを指定するとフォームのリモート + unobtrusive XHR送信が無効になります。 (デフォルトのフォームではリモート + unobtrusive XHRが有効になります。) |
:skip_enforcing_utf8 | trueを指定すると、送信時にutf8という名前の隠しフィールドが出力されなくなります。 |
:builder | フォームのビルドに使うオブジェクトをオーバーライドします。 |
:id | HTMLのid属性を指定します(オプション)。 |
:class | HTMLのclass属性を指定します(オプション)。 |
:data | HTMLのdata属性を指定します(オプション)。 |
:html | 上以外のHTML属性を使う場合に指定します(オプション)。 |
form_withで使えるヘルパーメソッド
form_withでHTMLを生成するためのヘルパーメソッドまとめたので下記の記事をご参照ください!
Railsのform_withでHTMLを生成するためのヘルパーメソッドまとめ
https://hirocorpblog.com/post-330/
終わりに
form_withを使うと手軽にformタグを生成することができます。(しかもセキュリティ保護付きで安心です。)
Rails5.1以上のかたは使いこなせるようにしましょう!