謎のエラーに苦しめられました。
結論から言うと原因は「routes.rb」への記載の順番でした。
個人ブログに同様の内容を書いておりましたが、技術的な内容はQiitaに集約することにしたので、こちらにも投稿します。
(参考)個人ブログ
※ バージョンは、Ruby:2.3.0、Rails:5.1.4です。
事象
本件に関係のある箇所を抜粋しています。
resources :users, only: [:show]
devise_for :users, controllers: { :omniauth_callbacks => "omniauth_callbacks", registrations: 'registrations'}
devise gemを利用してログイン機能を実装しています。
ユーザー詳細ページをつけるために、resources :users, only: [:show] で users#show のためのルーティングを設定しています。
before_action :sign_in_required, only: [:show]
def show
# 以下略
private
def sign_in_required
redirect_to new_user_session_url unless user_signed_in?
end
発生したエラー
(言われた通り大人しくCookieを消しましたが効果ありませんでした)
ログ
Started GET "/users/sign_in" for 127.0.0.1 at 2018-02-19 21:58:38 +0900
Processing by UsersController#show as HTML
Parameters: {"id"=>"sign_in"}
Redirected to http://localhost:3000/users/sign_in
Filter chain halted as :sign_in_required rendered or redirected
Completed 302 Found in 1ms (ActiveRecord: 0.0ms)
Started GET "/users/sign_in" for 127.0.0.1 at 2018-02-19 21:58:38 +0900
Processing by UsersController#show as HTML
Parameters: {"id"=>"sign_in"}
Redirected to http://localhost:3000/users/sign_in
Filter chain halted as :sign_in_required rendered or redirected
Completed 302 Found in 1ms (ActiveRecord: 0.0ms)
これの無限ループ
解決法
devise_for :users, controllers: { :omniauth_callbacks => "omniauth_callbacks", registrations: 'registrations'}
resources :users, only: [:show]
順番を入れ替えただけで直りました。マジか、、
分析
エラーしている状態のrails routesのログ
user GET /users/:id(.:format) users#show
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/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) registrations#cancel
new_user_registration GET /users/sign_up(.:format) registrations#new
edit_user_registration GET /users/edit(.:format) registrations#edit
user_registration PATCH /users(.:format) registrations#update
PUT /users(.:format) registrations#update
DELETE /users(.:format) registrations#destroy
POST /users(.:format) registrations#create
user_twitter_omniauth_authorize GET|POST /users/auth/twitter(.:format) omniauth_callbacks#passthru
user_twitter_omniauth_callback GET|POST /users/auth/twitter/callback(.:format) omniauth_callbacks#twitter
new_user_confirmation GET /users/confirmation/new(.:format) devise/confirmations#new
user_confirmation GET /users/confirmation(.:format) devise/confirmations#show
POST /users/confirmation(.:format) devise/confirmations#create
エラー解決した状態のrails routesのログ
Prefix Verb URI Pattern Controller#Action
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/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) registrations#cancel
new_user_registration GET /users/sign_up(.:format) registrations#new
edit_user_registration GET /users/edit(.:format) registrations#edit
user_registration PATCH /users(.:format) registrations#update
PUT /users(.:format) registrations#update
DELETE /users(.:format) registrations#destroy
POST /users(.:format) registrations#create
user_twitter_omniauth_authorize GET|POST /users/auth/twitter(.:format) omniauth_callbacks#passthru
user_twitter_omniauth_callback GET|POST /users/auth/twitter/callback(.:format) omniauth_callbacks#twitter
new_user_confirmation GET /users/confirmation/new(.:format) devise/confirmations#new
user_confirmation GET /users/confirmation(.:format) devise/confirmations#show
POST /users/confirmation(.:format) devise/confirmations#create
user GET /users/:id(.:format)
当然、
user GET /users/:id(.:format) users#show
の行の場所が変わるだけです。
ログをよく見てみると、
Started GET "/users/sign_in" for 127.0.0.1 at 2018-02-19 21:58:38 +0900
Processing by UsersController#show as HTML
Parameters: {"id"=>"sign_in"}
Redirected to http://localhost:3000/users/sign_in
GET "/users/sign_in" にアクセスしようとしてるけど、GET "/users/:id" に "id" = "sign_in" としてアクセスしちゃってる・・・
そして、 users#show はログインしていないとログインページに強制リダイレクトする設定になっているので、 GET "/users/sign_in" にアクセスして以下、無限ループです。
更に、routes.rbの記載の順番によって、エラー発生の有無が決まるのは、
Railsのルーティングは、ルーティングファイルの「上からの記載順に」マッチします。
のためでした。
(参考)Rails のルーティング | Rails ガイド
つまり、解決した時には、GET "/users/sign_in" にアクセスしようとした時に、GET "/users/:id" が一番上になかったために引っかからず、正しいルーティングを選択できたからでした。
ルーティングも奥が深いですね。
まだ知らないことばっかりで楽しいな〜(エラー最中はイライラが止まらないけど、解決して分析してスッキリするの好き)
ご指摘・ご感想等いただけますと大変嬉しいです!