rails7でdeviseのログアウトを使ったらうまく動かなかったので調査しました。調べてみるとrails7でjavascriptの挙動が変わっていたのでその辺もまとめました。
事象:deviseのdestroy_user_session_pathが効かない
deviseのdestroy_user_session_pathをクリックした際に
No route matches [GET] "/users/sign_out"
と出てしまった。
環境は下記
- rails7
- まだjavascriptの設定はしていない
原因:javascriptが動いていない
destroy_user_session_pathはdeleteメソッドで動きます。deleteメソッドはlink_toの場合、javascriptでgetメソッドからdeleteメソッドに変換されます。
今回javascriptが動いていなかったのでgetのままになり、上記のエラーが出ていました。
javascriptを有効化する
rails7のjavascriptはrails6のころと比べて大きく変わりました。importmapというものを使えるようになり、yarnなどを使わなくてよくなりました。
importmapを有効化するには
- importmap-rails のインストール(デフォルトでされている
- rails importmap:install
- config/importmap.rbに「pin “@hotwired/turbo-rails”, to: “turbo.js”」
- app/javascript/application.jsに「import “@hotwired/turbo-rails”」
- <%= javascript_importmap_tags %>をapp/views/layouts/application.html.erbに
importmap-rails のインストール(デフォルトでされている
新規のRails 7プロジェクトを作成する際、デフォルトでimportmap-railsがインストールされます。既存のプロジェクトでimportmap-railsを使用する場合は、Gemfileにgem 'importmap-rails'
を追加し、bundle install
コマンドを実行します。
rails importmap:install
rails importmap:install
ターミナルでrails importmap:install
を実行します。これにより、Importmapの設定ファイルconfig/importmap.rb
や、JavaScriptを記述するためのapp/javascript/application.js
ファイルなどが生成されます。
config/importmap.rbに「pin “@hotwired/turbo-rails”, to: “turbo.js”」
config/importmap.rb
pin "@hotwired/turbo-rails", to: "turbo.js"
上記を追記。これにより、@hotwired/turbo-rails
パッケージをImportmapに登録します。
app/javascript/application.jsに追記
app/javascript/application.js
import "@hotwired/turbo-rails"
このコードは、@hotwired/turbo-rails
パッケージをアプリケーションにインポートします。
<%= javascript_importmap_tags %>をapp/views/layouts/application.html.erbに
app/views/layouts/application.html.erb
ファイルにJavaScriptを読み込むためのタグを追加します。</body>
タグの直前に以下の行を追加します:
<%= javascript_importmap_tags %>
以上の手順を実行することで、ImportmapでJavaScriptを有効にし、@hotwired/turbo-railsを使用してRails UJSの機能(例:method: :delete
)を利用できるようになります。これにより、ログアウトリンクなど、JavaScriptに依存する機能が正常に動作するようになるはずです。
link_toの設定
<%= link_to "ログアウト", destroy_user_session_path, data: { turbo_method: :delete } %>
上記のようにdeleteメソッドを使う際にdata: { turbo_method: :delete } で書くとjavascriptが有効になります。