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?

Rails API×DeviseAuthTokenでdestroyアクションを実行するとActiveRecord::RecordNotFound

Posted at

前提条件

  • Rails API × React(TS)でSPAを構築
  • 使用しているgemのバージョン
    • rails: 8.0.1
    • devise: 4.9.4
    • devise_token_auth: 1.2.5
  • DeviseAuthTokenを用いてトークン認証による認証基盤を実装していた

発生した問題

users_controller.rbdestroyアクションで ActiveRecord::RecordNotFoundエラーが発生した

  def destroy
    if @user&.destroy
      render json: { message: 'ユーザーが削除されました' }, status: :ok
    else
      render json: { errors: ['ユーザーの削除に失敗しました'] }, status: :unprocessable_entity
    end
  end

が実行されると、次のログを得た

backend-1   |   User Destroy (1.1ms)  DELETE FROM "users" WHERE "users"."id" = 92 /*action='destroy',application='Myapp',controller='users'*/
backend-1   |   ↳ app/controllers/api/v1/users_controller.rb:11:in 'Api::V1::UsersController#destroy'
backend-1   |   TRANSACTION (2.2ms)  COMMIT /*action='destroy',application='Myapp',controller='users'*/
backend-1   |   ↳ app/controllers/api/v1/users_controller.rb:11:in 'Api::V1::UsersController#destroy'
backend-1   |   User Load (0.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 92 LIMIT 1 /*action='destroy',application='Myapp',controller='users'*/
backend-1   | Completed 404 Not Found in 36835ms (Views: 0.5ms | ActiveRecord: 13.4ms (5 queries, 0 cached) | GC: 0.0ms)
backend-1   | 
backend-1   | 
backend-1   |   
backend-1   | ActiveRecord::RecordNotFound (Couldn't find User with [WHERE "users"."id" = $1]):
backend-1   |   
backend-1   | activerecord (8.0.1) lib/active_record/relation/finder_methods.rb:425:in 'ActiveRecord::FinderMethods#raise_record_not_found_exception!'
backend-1   | activerecord (8.0.1) lib/active_record/relation/finder_methods.rb:135:in 'ActiveRecord::FinderMethods#take!'
backend-1   | activerecord (8.0.1) lib/active_record/relation/finder_methods.rb:118:in 'ActiveRecord::FinderMethods#find_by!'
backend-1   | activerecord (8.0.1) lib/active_record/persistence.rb:833:in 'ActiveRecord::Persistence#_find_record'
backend-1   | activerecord (8.0.1) lib/active_record/persistence.rb:748:in 'block in ActiveRecord::Persistence#reload'
backend-1   | activerecord (8.0.1) lib/active_record/relation.rb:1373:in 'ActiveRecord::Relation#_scoping'
backend-1   | activerecord (8.0.1) lib/active_record/relation.rb:548:in 'ActiveRecord::Relation#scoping'
backend-1   | activerecord (8.0.1) lib/active_record/scoping/default.rb:51:in 'ActiveRecord::Scoping::Default::ClassMethods#unscoped'
backend-1   | activerecord (8.0.1) lib/active_record/persistence.rb:748:in 'ActiveRecord::Persistence#reload'
backend-1   | activerecord (8.0.1) lib/active_record/attribute_methods/dirty.rb:64:in 'ActiveRecord::AttributeMethods::Dirty#reload'
backend-1   | activerecord (8.0.1) lib/active_record/autosave_association.rb:241:in 'ActiveRecord::AutosaveAssociation#reload'
backend-1   | activestorage (8.0.1) lib/active_storage/attached/model.rb:277:in 'ActiveStorage::Attached::Model#reload'
backend-1   | devise_token_auth (1.2.5) app/controllers/devise_token_auth/concerns/set_user_by_token.rb:112:in 'DeviseTokenAuth::Concerns::SetUserByToken#update_auth_header'
backend-1   | activesupport (8.0.1) lib/active_support/callbacks.rb:361:in 'block in ActiveSupport::Callbacks::CallTemplate::MethodCall#make_lambda'
backend-1   | activesupport (8.0.1) lib/active_support/callbacks.rb:207:in 'ActiveSupport::Callbacks::Filters::After#call'

解決方法

destroyアクションがあるコントローラ(自分であればusers_controller.rb)で、

 skip_after_action :update_auth_header, only: [:destroy]

を追加し、update_auth_headerコールバックをスキップする。

class Api::V1::UsersController < ApplicationController
...
  skip_after_action :update_auth_header, only: [:destroy]

...

  def destroy
    if @user&.destroy
      render json: { message: 'ユーザーが削除されました' }, status: :ok
    else
      render json: { errors: ['ユーザーの削除に失敗しました'] }, status: :unprocessable_entity
    end
  end

解決に至った根拠

  1. destroyアクションの至る所にbinding.irbを仕込む
  2. @user&.destroyが実行された後に@user.reloadを実行するとActiveRecord::RecordNotFoundが発生することを発見
  3. ログを見て、devise_auth_tokenupdate_auth_headerreloadを呼び出していることを発見
  4. devise_auth_tokenのissueを見に行き、同じような問題を抱えている人を検索
    https://github.com/lynndylanhurley/devise_token_auth/issues/1220
    おんなじことで悩んでる人おるやん...笑
  5. 公式ドキュメントにも、ユーザーを破棄する場合は update_auth_headerをスキップしてくださいと書いてありますね。
    https://devise-token-auth.gitbook.io/devise-token-auth/usage/controller_methods

ソース

まとめ

生成AIに頼りすぎず、ちゃんとログと公式ドキュメントを読もう。

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?