67
66

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Rails】deviseのビューのform_forをform_withに置き換える

Last updated at Posted at 2019-03-12

はじめに

deviseが元々保証してるビューを使ったとき、ユーザー登録のためのヘルパーメソッドは「form_for」によって実装されています。(devise(4.6.1)、2019年3月12日時点)

「今後はform_withに変えていこうぜ」というお達しも出ていることですし、Rails5.1以降のアプリでdeviseが自動生成したビューをそのまま使っている場合は、自分で変更することも検討していいかもしれません。

今回は、app/views/devise/registrations配下の「new.html.erb」について、「form_for」から「form_with」に置き換えてみます。

置き換える

form_for(置き換え前)

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>

(ブラウザ上に表示されるhtmlソースコード)
<form class="new_user" id="new_user" action="/users" accept-charset="UTF-8" method="post">
  <input name="utf8" type="hidden" value="✓">

  <!-- ... -->

</form>

form_with(置き換え後)

<%= form_with model: @user, url: user_registration_path, id: 'new_user', class: 'new_user', local: true do |f| %>

(ブラウザ上に表示されるhtmlソースコード)
<form class="new_user" id="new_user" action="/users" accept-charset="UTF-8" method="post">
  <input name="utf8" type="hidden" value="✓">

  <!-- ... -->

</form>

これでform_withでの置き換えは完了です。
書き換えたオプションの詳細を確認しましょう。

form_withのオプションについて

local: true

自動で行われるAjax通信を無効化するためのオプションです。
このオプションによって、<form>の中に「data-remote="true"」という記述がされることを防いでいます。
このオプションがないとJavaScriptによってレンダリングし、リダイレクト処理が行われないため、画面が遷移しなくなります。

model: @user

ここはモデル名によって変わってきますが、今回はUserモデルでの実装として考えているので、@￰user(User.new)を指定します。
form_for(置き換え前)でのresourceに相当します。

url: user_registration_path

form_forでのurl: registration_path(resource_name)に当たりますが、より明示的になるよう記述を変更しました。
このオプションはhtml上での「action="/users"」に当たります。

id: 'new_user' と class: 'new_user'

html上での「class="new_user" id="new_user"」に当たる箇所です。
form_withでは自動で付与されないようなので、明示的に記入します。

as: resourceに当たる所がform_withで書き換えたビューにないけどどこいった?

これは各inputフィールドのname属性を明示的にグループ化するためによく使われる記述ですが、
form_forでもform_withでも、モデル名(リソース名)で自動補完的にグループ化されるようなので、今回の場合は対応するものをform_withで準備しなくても問題はありません。

ただ、form_forでの:asオプションの挙動と、form_withの場合ではどのオプションを使えばいいかということについては、確認しておきましょう。

挙動の確認

form_forでの:asオプション

<%= form_for(resource, as: 'hoge', url: registration_path(resource_name)) do |f| %>

(ブラウザ上に表示されるhtmlソースコード)
<form class="new_hoge" id="new_hoge" action="/users" accept-charset="UTF-8" method="post">
  <input name="utf8" type="hidden" value="✓">
  <input type="hidden" name="authenticity_token" value="SgDrx+kPXXBTULNk6U8Au4SxYUaVMs6eFTHW+O80UT4KFQnp7hRV+u6F0TsTen44yjGNdd/xWKikYtSNT1uPrQ==">
  

  <div class="field">
    <label for="hoge_email">Email</label><br>
    <input autofocus="autofocus" autocomplete="email" type="email" value="" name="hoge[email]" id="hoge_email">
  </div>

   <!-- ... -->

</form>

<form>のid、classと、laberのfor属性と、inputフィールドのname属性とidに「hoge」が反映されて表示されます。

form_withでの:scopeオプション

form_withでは:asオプションは機能しないので:scopeを使いましょう。

<%= form_with model: @user, scope: 'hoge', url: user_registration_path, id: 'new_user', class: 'new_user', local: true do |f| %>

(ブラウザ上に表示されるhtmlソースコード)

<form id="new_user" class="new_user" action="/users" accept-charset="UTF-8" method="post">
  <input name="utf8" type="hidden" value="✓">
  <input type="hidden" name="authenticity_token" value="1TJ87nrrWc02LwzHkKqPVPdLUwghnekawy5C848Yp0SVJ57AffBRR4v6bphqn/HXucu/O2tefyxyfUCGL3d51w==">
  

  <div class="field">
    <label for="hoge_email">Email</label><br>
    <input autofocus="autofocus" autocomplete="email" type="email" value="" name="hoge[email]" id="hoge_email">
  </div>

  <!-- ... -->

</form>

laberのfor属性とinputフィールドのname属性とidに「hoge」がありますね。
フォーム自体の(1行目の<form>の)idとclassはオプションで明示的にしている「id: 'new_user', class: 'new_user'」に従います。
(というより、そもそも:scopeオプションはそこに関与しません。)

:scopeオプションのおかげでinputフィールドのname属性がhogeでグループ化されている

ということはコントローラではparams[:hoge]でアクセスできます。
ストロングパラメータとしてはparams.require(:hoge).permit(:email, :fuga, :foo)といった形でアクセスしましょう。

:scopeオプションを使用しない場合は、モデル名(user)でグループ化してくれるので、params[:user]でアクセスできます。

参考にさせて頂いたサイト・記事

[Rails 5.1] ‘form_with’ APIドキュメント完全翻訳
https://techracho.bpsinc.jp/hachi8833/2017_05_01/39502

【Rails 5】(新) form_with と (旧) form_tag, form_for の違い
https://qiita.com/hmmrjn/items/24f3b8eade206ace17e2

「ActionView::Helpers::FormHelper」
https://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_with

「MDN web docs <form>」
https://developer.mozilla.org/ja/docs/Web/HTML/Element/form

67
66
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
67
66

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?