LoginSignup
13
8

More than 3 years have passed since last update.

Ruby on RailsのDevise gemを使ってエラーCouldn't find User with 'id'=sign_inが出た時の対処法

Last updated at Posted at 2020-08-12

発生したエラー内容

ユーザー登録やログイン認証のためにDevise gemを入れて、さらに自分でUser Controllerを作ったら、以下のエラーメッセージが出て、deviseのログイン画面やユーザー登録画面が動かなくなる、ユーザー情報画面が表示されないといったエラーが発生しました。

  • ActiveRecord::RecordNotFound in UsersController#show
  • Couldn't find User with 'id'=sign_in(sign_up)

問題が発生した実行環境

実行環境による差分があるとは思いませんが、念のため当方の実行環境を載せておきます。
- Cloud9(Ubuntu)
- ruby 2.6.3
- Rails 6.0.3.2
- Devise 4.7.2

問題の原因

この問題が発生したのは、user/:idというルーティングが、user/sign_inやuser/sign_upを包括してしまっていたためでした。Railsのルーティングは上から順に読み込んでいき、合致するルーティングを探しているため、resources :users が先に読み込まれて、sign_inやsign_upをidだと認識してしまったことが原因だったようです。

                   users GET    /users(.:format)                  users#index
                    user GET    /users/:id(.:format)              users#show
        new_user_session GET    /users/login(.:format)            users/sessions#new
            user_session POST   /users/login(.:format)            users/sessions#create
    destroy_user_session DELETE /users/logout(.:format)           users/sessions#destroy
       new_user_password GET    /users/password/new(.:format)     devise/passwords#new
      edit_user_password GET    /users/password/edit(.:format)    devise/passwords#edit
           user_password PATCH  /users/password(.:format)         devise/passwords#update
                         PUT    /users/password(.:format)         devise/passwords#update
                         POST   /users/password(.:format)         devise/passwords#create
cancel_user_registration GET    /users/cancel(.:format)           users/registrations#cancel
   new_user_registration GET    /users/signup(.:format)           users/registrations#new
  edit_user_registration GET    /users/edit(.:format)             users/registrations#edit
       user_registration PATCH  /users(.:format)                  users/registrations#update
                         PUT    /users(.:format)                  users/registrations#update
                         DELETE /users(.:format)                  users/registrations#destroy
                         POST   /users(.:format)                  users/registrations#create

上のようにuser GET /users/:id(.:format) users#show がDevise Gemのルーティングより上に来てしまっている場合、routes.rbは以下のように記述されているかと思います。

routes.rb
Rails.application.routes.draw do
  resources :users, only: [:index, :show]
  devise_for :users, controllers: {
        sessions: 'users/sessions',
        registrations: 'users/registrations'},
    path_names: {
      sign_in: 'login',
      sign_out: 'logout',
      sign_up: 'signup'
    }
end

解決策

routes.rbの書き方を修正します。具体的には、resources :users, only: :index, :showをdevise for :usersの後ろに移動することで解決します。

routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: {
        sessions: 'users/sessions',
        registrations: 'users/registrations'},
    path_names: {
      sign_in: 'login',
      sign_out: 'logout',
      sign_up: 'signup'
    }
  resources :users, only: [:index, :show]
end

正しい順番で記載してからrails routesで確認してみると、user GET /users/:id(.:format) users#showよりもDevise gemのルーティングが上に来ていることが確認できるかと思われます(上記コードではpath_namesを使ってsign_inをloginに、sign_outをlogoutに変更していますが、大意に影響はありません)。

        new_user_session GET    /users/login(.:format)            users/sessions#new
            user_session POST   /users/login(.:format)            users/sessions#create
    destroy_user_session DELETE /users/logout(.:format)           users/sessions#destroy
       new_user_password GET    /users/password/new(.:format)     devise/passwords#new
      edit_user_password GET    /users/password/edit(.:format)    devise/passwords#edit
           user_password PATCH  /users/password(.:format)         devise/passwords#update
                         PUT    /users/password(.:format)         devise/passwords#update
                         POST   /users/password(.:format)         devise/passwords#create
cancel_user_registration GET    /users/cancel(.:format)           users/registrations#cancel
   new_user_registration GET    /users/signup(.:format)           users/registrations#new
  edit_user_registration GET    /users/edit(.:format)             users/registrations#edit
       user_registration PATCH  /users(.:format)                  users/registrations#update
                         PUT    /users(.:format)                  users/registrations#update
                         DELETE /users(.:format)                  users/registrations#destroy
                         POST   /users(.:format)                  users/registrations#create
                   users GET    /users(.:format)                  users#index
                    user GET    /users/:id(.:format)              users#show

この方法に直したら問題なくログインできるようになりました。

補足:devise_forメソッドで生成されるルーティングを整理してみました

devise_forメソッドを使ったルーティングがわかりづらかったので、resources :usersで生成されるルーティングとの対応表を作りました。合わせてご査収ください。

resource :users devise_for
users#index なし
users#new devise/registration#new
users#create devise/registration#create
users#edit devise/registration#edit
users#show なし
users#update devise/registration#update
users#destroy devise/registration#destroy
13
8
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
13
8