54
34

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

「localhost でリダイレクトが繰り返し行われました。」はルーティングのせいだった、Ruby on Rails エラーの分析

Last updated at Posted at 2018-03-31

謎のエラーに苦しめられました。
結論から言うと原因は「routes.rb」への記載の順番でした。

個人ブログに同様の内容を書いておりましたが、技術的な内容はQiitaに集約することにしたので、こちらにも投稿します。
(参考)個人ブログ

※ バージョンは、Ruby:2.3.0、Rails:5.1.4です。

事象

本件に関係のある箇所を抜粋しています。

routes.rb
  resources :users, only: [:show]
  devise_for :users, controllers: { :omniauth_callbacks => "omniauth_callbacks", registrations: 'registrations'}

devise gemを利用してログイン機能を実装しています。
ユーザー詳細ページをつけるために、resources :users, only: [:show] で users#show のためのルーティングを設定しています。

users_controller.rb
  before_action :sign_in_required, only: [:show]
  def show
  # 以下略
application_controller.rb
  private
    def sign_in_required
      redirect_to new_user_session_url unless user_signed_in?
    end

発生したエラー
スクリーンショット 2018-03-30 22.13.24.png
(言われた通り大人しく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)

これの無限ループ

解決法

routes.rb
  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" が一番上になかったために引っかからず、正しいルーティングを選択できたからでした。

ルーティングも奥が深いですね。
まだ知らないことばっかりで楽しいな〜(エラー最中はイライラが止まらないけど、解決して分析してスッキリするの好き)

ご指摘・ご感想等いただけますと大変嬉しいです!

54
34
2

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
54
34

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?