viewでform_with
メソッドを利用してログインフォームを作ったが、local: true
にしているにも拘らず、render 'new'
でログインフォームを再描画できずにはまったのでメモ。
TL;DR
Rails 7では、form_withに対してlocal: true
の代わりにオプションでdata: { turbo: false }
と指定する。
環境
$ ruby -v
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
$ rails -v
Rails 7.0.3
Rails.application.routes.draw do
...
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
...
end
説明
以下ログインフォームのviewとセッション用のcontroller。
...
<div class="login__forms">
<%= form_with(url: login_path, scope: :session, local: true) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.submit %>
<% end %>
</div>
...
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by(name: params[:session][:name])
if user&.authenticate(params[:session][:password])
...
else
flash.now[:danger] = 'ログイン失敗やで'
render 'new'
end
end
end
Railsのログを見ると/loginにPOSTしてレンダリングまではできているらしいが、flashの内容などはブラウザには反映されず。
Rendering sessions/new.html.erb within layouts/application
Rendered sessions/new.html.erb within layouts/application (Duration: 5.5ms | Allocations: 1070)
form_with
はRails5以降、デフォルトでAjaxを使おうとするから無効にしたいなら明示的にlocal: true
と指定する必要がある。
ググると↑の情報はよく出てくるが、それでもうまくいかなくて困っているのである。
正解
正解はTurboを無効にするでした。
rails "local: true" doesn't work
とかでググると出てきました。
Rails 7ではTurboがデフォルトで有効になっており、Turboが有効ではページの部分更新ができないので、今回のような場合には無効にする必要があったのでした。
めでたしめでたし。
結果的にログインフォームのviewはこうなりました。
...
<div class="login__forms">
<%= form_with(url: login_path, scope: :session,
data: { turbo: false }) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.submit %>
<% end %>
</div>
...
以上です。
ありがとうございました。