DHH流ルーティングの導入しようとした際にハマったこと

## はじめに
とあるWebアプリケーションで、通常のお知らせ、メンテナンス情報、障害情報の三種類のお知らせを表示させるために

```rb
class InformationsController < ApplicationController
  def index
  end

  def maintenance
  end

  def trouble
  end
end
```

ようなコントローラーを作成したとします。規則性のないメソッド名やコントローラーの肥大化など問題に発展しやすいです。

そこで、[DHHはどのようにRailsのコントローラを書くのか](http://postd.cc/how-dhh-organizes-his-rails-controllers/)の記事では、DHH流のルーティングを学ぶことで、本問題の解決法が提示されています。このDHH流ルーティングを導入しようとした際に、ハマったことをまとめます。


## DHH流ルーティングとは
[翻訳記事](http://postd.cc/how-dhh-organizes-his-rails-controllers/)によると

* RESTの原則に従う場合は、全てのコントローラーで例外なくその原則に従うべき
* 全てのコントローラーでは、デフォルトCRUDの`index` , `show`, `new`, `edit`, `create`, `update`, `destroy`メソッドのみを持つこと
* 例えばメールボックの受信一覧とペンディング一覧を閲覧するアクションを持つコントローラーを作る場合は、以下のように `index`と`pendings`アクションを作るのではなく、

```ruby
class InboxesController < ApplicationController
  def index
  end

  def pendings
  end
end
```

`index` という単一のメソッドだけを持つ`Inboxes::PendingsController`を作成する。これにより独自のスコープとフィルターを提供することができるようになる。

```ruby
class InboxesController < ApplicationController
  def index
  end
end
```

```ruby
class Inboxes::PendingsController < ApplicationController
  def index
  end
end
```

## ルーティングを設定する

先程の `InboxesController` と `Inboxes::PendingsController`を実現するため、以下３パターンを試しました。

### resourcesのネスト

```rb:config/routes.rb
  resources :inboxes, only: [:index] do
    resources :pendings, only: [:index]
  end
```

```shell-session
$ rails routes
        Prefix Verb URI Pattern                           Controller#Action
inbox_pendings GET  /inboxes/:inbox_id/pendings(.:format) pendings#index
       inboxes GET  /inboxes(.:format)                    inboxes#index
```

inbox_pendings側をみると、URIパターンは希望通りですが、`Controller#Action`が `inboxes/pendings#index`となってくれません。

### namespace

次に `namespace` でネストさせます。

```rb:config/routes.rb
  resources :inboxes, only: [:index]
  namespace :inboxes do
    resources :pendings, only: [:index]
  end
```

```shell-session
$ rails routes
          Prefix Verb URI Pattern                 Controller#Action
         inboxes GET  /inboxes(.:format)          inboxes#index
inboxes_pendings GET  /inboxes/pendings(.:format) inboxes/pendings#index
```

`Controller#Action`は希望通り、`inboxes/pendings#index`とinboxesディレクトリ配下となりましたが、URIパターンを見ると、`:inbox_id`が消えてしまいました・・・。

### resourcesのネストとmodule指定

```rb:config/routes.rb
  resources :inboxes, only: [:index] do
    resources :pendings, only: [:index], module: 'inboxes'
  end
```

```shell-session
$ rails routes
        Prefix Verb URI Pattern                           Controller#Action
inbox_pendings GET  /inboxes/:inbox_id/pendings(.:format) inboxes/pendings#index
       inboxes GET  /inboxes(.:format)                    inboxes#index
```

先程のresourcesのネストは同じですが、moduleオプションを付けることで、名前空間が設定でき、`inboxes`ディレクトリ配下に`pendings_controller`が作成できるになり、ファイル配置もすっきりさせることができるようになりました。

## 終わりに
resoucesとmoduleオプションを利用することで、簡単に導入することができ、その結果

* 責務に応じたコントローラー分割
* シンプルなコードの実現

という効果が得られるので、積極的に取り入れていきたいです。

## 参考
* [How DHH organizes his Rails controllers \- Jerome's Adventures in Software](http://jeromedalbert.com/how-dhh-organizes-his-rails-controllers/)
* [DHH流のルーティングで得られるメリットと、取り入れる上でのポイント \- KitchHike Tech Blog](http://tech.kitchhike.com/entry/2017/03/07/190739)