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

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

個人ブログに同様の内容を書いておりましたが、技術的な内容はQiitaに集約することにしたので、こちらにも投稿します。
[（参考）個人ブログ](http://ysk-pro.hatenablog.com/entry/2018/02/19/225131)

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

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

```ruby:routes.rb
  resources :users, only: [:show]
  devise_for :users, controllers: { :omniauth_callbacks => "omniauth_callbacks", registrations: 'registrations'}
```
devise gemを利用してログイン機能を実装しています。
ユーザー詳細ページをつけるために、resources :users, only: [:show] で users#show のためのルーティングを設定しています。

```ruby:users_controller.rb
  before_action :sign_in_required, only: [:show]
  def show
  # 以下略
```

```ruby: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](https://qiita-image-store.s3.amazonaws.com/0/235935/0da11a0d-4c40-08f0-585d-1868cc27ea7d.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)

これの無限ループ
```

# 解決法
```ruby: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 ガイド](https://railsguides.jp/routing.html)

つまり、解決した時には、GET "/users/sign_in" にアクセスしようとした時に、GET "/users/:id" が一番上になかったために引っかからず、正しいルーティングを選択できたからでした。

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

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