0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Deviseを使ってログアウトボタンが押せなかった話

Posted at

はじめに

今回は、Railsで認証Gemをdeviseを使用したときに
ログアウトボタンを作成したときに,
DELETEリクエストがGETになっていたために
できませんでした。その時のメモを:frowning2:

開発環境

  • Docker 27.3.1
  • Ruby 3.3.6
  • Rails 7.2.2
  • PostgreSQL 17.2

解決方法

bash
$ yarn add @rails/ujs 
application.js
import Rails from "@rails/ujs"; #この2行追加
Rails.start();
bash
$ docker compose up
$ docker compose down

これでログアウトボタンをDELETEでいけます。

例)ログアウト link_to
<%= link_to 'ログアウト', destroy_user_session_path, method: :delete, data: { turbo: false } %>

Turboについて

Rails7以降でTurboが使用されTurboはフォームやリンクを AJAX 的に処理するため、通常のリクエストが無効化されることあります。ログアウトリンクで Turbo を無効にするため、次のようにdata: { turbo: false }をログアウトボタンに記載します。

@rails/ujs が動作する仕組み

ページロード時に @rails/ujs がHTMLを監視。
data-method 属性を持つリンクがクリックされた場合、JavaScript で動的に

を生成し、指定されたHTTPメソッド(例:DELETE)でリクエストを送信します。
これにより、ブラウザが直接サポートしていない DELETE メソッドでもサーバーにリクエストを送ることができます

なぜ@rails/ujsが必須なのか?

@rails/ujs を読み込まないと、data-method 属性を処理するJavaScriptが動作しないため、リンクをクリックしてもただの通常のリンク(GET リクエスト)として扱われます。
この結果、Railsのルーティングで期待されるHTTPメソッドが一致せず、エラーになります。

以下のコードで @rails/ujs がない場合の動作と、ある場合の動作を比較します。

erb
<%= link_to "Logout", destroy_user_session_path, method: :delete %>

生成されるHTML

html
<a rel="nofollow" data-method="delete" href="/users/sign_out">Logout</a>

@rails/ujs がない場合

ブラウザは data-method を無視。
GET /users/sign_out がサーバーに送信される。
RailsはDELETE /users/sign_outを期待しているため、エラーが発生。

@rails/ujs がある場合

data-method="delete" を検出。
JavaScriptが自動的に

を生成して DELETE リクエストを送信。
Railsは正しいHTTPメソッドを受け取るため、ログアウト処理が正常に行われる。
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?