概要
Rails5.1から「form_forヘルパー」と「form_tagヘルパー」が非推奨になっていると知ったので、新たに導入された「form_with」を使用しようとしたが少し手間取ったのでメモ。
解決までの内容に興味がなければ「解決方法」に最終的なコードがあるので他は読み飛ばしてください。
実現したいこと
Railsチュートリアル7章、リスト7.15および完成系のリスト7.27を「form_with」を使用して実装する。
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(@user) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.email_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>
</div>
</div>
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(@user, url: signup_path) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
<%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>
</div>
</div>
発生したエラー
まず、リスト7.15を(コード1)のように書き換えて実装。
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(model: @user) do |f| %> <%# この行のみ変更 %>
<%= f.label :name %>
<%# 後略 %>
問題なくブラウザには表示されたが、チュートリアルを進めると「図 7.15: ユーザー登録失敗」が表示されない。
ん?と思いコンソールを確認すると(図1)のように表示されていた。
Started POST "/users" for ::1 at 2020-03-01 20:07:59 +0900
(0.5ms) SELECT sqlite_version(*)
(0.2ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
Processing by UsersController#create as JS
Parameters: {"authenticity_token"=>"1kulZpjCeawCkV6pT76gpjkNMJKKZCgx5x2xOfZz6ftXd+oLZX7UMjRRejscuv4kSEIHcPGh86nlR7FR9Fz/Uw==", "user"=>{"name"=>"", "email"=>"", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"登 録"}
Completed 500 Internal Server Error in 12ms (ActiveRecord: 0.8ms | Allocations: 5794)
ActiveModel::ForbiddenAttributesError (ActiveModel::ForbiddenAttributesError):
なんでブラウザに表示されないんだろうと疑問に感じながらも
ActiveModel::ForbiddenAttributesError
の一文があるのでチュートリアルと同様のエラーは発生していると判断してそのまま進める。
すると「図 7.18: ユーザー登録失敗時のエラーメッセージ」も表示されない!?
さすがにこれは問題だと思いあれこれ調べるとform_withはデフォルトでは非同期通信(Ajax)になっているという。
(図1)のエラーメッセージのこの一文で判断できたらしい。
Processing by UsersController#create as JS #JavaScriptとして処理する(?)
解決方法
最終的なコードが(コード2)
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(model: @user, url: signup_path, local: true) do |f| %> <%# この行のみ変更 %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
<%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>
</div>
</div>
form_withを同期通信にするにはオプションで
local: true
を加えればOK!
後書き
ちゃんと学習してから使用していればこんな初歩的なつまずきはなかったのでしょう。
常に変化し続けるこの業界では学び続けることが本当に大切なんだなと実感した出来事でした。