ルーティングの定義場所を調べる

## やりたいこと

あるルーティングがどこで定義されているかを調べたい。

## 例

巨大な `config/routes.rb` ファイルがあり、たくさんのルーティングが定義されている。

```config/routes.rb
# 1,000 行を超えた巨大な routes.rb ファイル。
Rails.application.routes.draw do
  # 略

  resources :brands, only: %i(index show) do
    resources :yoyos
  end

  # 略
end
```

`bin/rails routes --unused` コマンドを実行して、使用していないルーティングを調べてみる。そうすると `BrandsController` は `only` オプションで `index` と `show` しか定義していないにもかかわらず、なぜか `create`, `new`, `edit`, `update`, `destroy` といった他のアクションのルーティングも定義されている。

今回はこれらの想定していないルーティングがどこで定義されているかを調べてみる。

```shell-session
$ bin/rails routes --unused
Found 6 unused routes:

         Prefix Verb   URI Pattern                                Controller#Action
                POST   /brands(.:format)                          brands#create
      new_brand GET    /brands/new(.:format)                      brands#new
     edit_brand GET    /brands/:id/edit(.:format)                 brands#edit
                PATCH  /brands/:id(.:format)                      brands#update
                PUT    /brands/:id(.:format)                      brands#update
                DELETE /brands/:id(.:format)                      brands#destroy
```

## 方法

例えば `brands#create` のルーティングがどこで定義されているのか調べてみよう。Rails コンソールで以下のコードを実行する。

```rb
# それぞれの返り値の型のメモ。
# Rails.application.routes
#=> #<Rails::Engine::LazyRouteSet:0x000000012a8ffa18>
# Rails.application.routes.routes
#=> #<ActionDispatch::Journey::Routes:0x00000001299f45c8>
# Rails.application.routes.routes.first
#=> #<ActionDispatch::Journey::Route:0x000000012a712db8>
routes = Rails.application.routes.routes
route = routes.find { it.requirements in { controller: 'brands', action: 'create' } }
route.source_location
#=> "/Users/quanon/workspace/mogura_no_yoyo_shop/config/routes.rb:512"
```

どうやら `config/routes.rb` の 512 行目で定義されているらしい。その行を見てみる。

```config/routes.rb
Rails.application.routes.draw do
  # 略

  resources :brands, only: %i(index show) do
    resources :yoyos
  end

  # 略

  resources :brands do # 512 行目
    resources :bearings
  end
end
```

`resources :brands` が再度呼びだされていて、かつ `only` オプションでのアクションの指定が無いせいで余計なルーティングが定義されてしまっていた。(本来は 1 つの `resources :brands` にまとめるべきだが) 試しに、次のように `only: %i(index show)` を指定してみる。

```config/routes.rb
Rails.application.routes.draw do
  # 略

  resources :brands, only: %i(index show) do
    resources :yoyos
  end

  # 略

  resources :brands, only: %i(index show) do
    resources :bearings
  end
end
```

そうすると、余計なルーティングを削除することができた。

```shell-session
$ bin/rails routes --unused
No unused routes found.
```

## おまけ: 未使用のルーティング一覧を取得する

`bin/rails routes --unused` コマンドではなく Rails コンソールで未使用のルーティング一覧を取得することもできる。

```rb
require 'rails/commands/unused_routes/unused_routes_command'

routes = Rails.application.routes.routes
unused_routes = routes.select { Rails::Command::UnusedRoutesCommand::RouteInfo.new(it).unused? }
unused_routes.map { it.requirements.values_at(:controller, :action).join('#') }
#=> ["brands#create", "brands#new", "brands#edit", "brands#update", "brands#update", "brands#destroy"]
```

## バージョン情報

```rb
RUBY_VERSION
#=> "3.4.1"
Rails.version
#=> "8.0.1
```

## 参考

### Rails

Rails コンソール上でルーティングを検索したり参照したりする方法を調べるにあたり、以下の Ruby ファイルを参考にした。

- https://github.com/rails/rails/blob/v8.0.1/railties/lib/rails/commands/unused_routes/unused_routes_command.rb
- https://github.com/rails/rails/blob/v8.0.1/actionpack/lib/action_dispatch/routing/inspector.rb