はじめに
こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。
Rails API モードで devise_token_auth
を導入した際、
「before_action :authenticate_user!
が効かない!」「current_user
が常に nil!」
といった現象に遭遇したことはありませんか?
特に API を api/v1/auth
のような 名前空間付きルート で定義した場合、
ヘルパーメソッドの名前が変わることが原因です。
問題の状況
通常の Devise(名前空間なし)
# routes.rb
mount_devise_token_auth_for 'User', at: 'auth'
この場合は以下が利用可能です。
before_action :authenticate_user!
current_user
名前空間付き API の場合
# routes.rb
namespace :api do
namespace :v1 do
mount_devise_token_auth_for 'User', at: 'auth'
end
end
この場合は 自動的にスコープ名が api_v1_user
になるため、
before_action :authenticate_api_v1_user!
current_api_v1_user
というメソッド名になります。
→ authenticate_user!
/ current_user
は使えなくなる!
なぜこうなるのか?
devise_token_auth
は Devise のスコープ機能を使っており、
ルーティングのスコープ名(ここでは api_v1
)を元に
ヘルパーメソッドを自動生成します。
つまり、名前空間を切ると自動的に api_v1_user
スコープが作られ、
ヘルパーもそれに合わせて生成されます。
解決策
方法 1: そのまま使う
スコープ名が変わるのを前提に、authenticate_api_v1_user!
/ current_api_v1_user
をそのまま利用する。
メリット
- Devise の設計通りでシンプル
- 複数スコープ(Admin / Teacher)でも安全に使える
デメリット
- 毎回長い名前を書く必要がある
方法 2: alias_method で統一する
ApplicationController
でエイリアスを作り、
current_user
/ authenticate_user!
として使えるようにする。
class ApplicationController < ActionController::API
alias_method :current_user, :current_api_v1_user
alias_method :authenticate_user!, :authenticate_api_v1_user!
end
どの方法を選ぶべき?
-
API が 1 種類のユーザーだけ(User のみ)
→alias_method
で統一したほうが楽 -
Admin / Teacher など複数ユーザーを扱う予定がある
→current_api_v1_user
のまま運用したほうが安全
まとめ
- 名前空間を切るとヘルパーメソッド名が
api_v1_user
になる -
authenticate_user!
/current_user
を使いたい場合は alias_method で統一可能