はじめに
とあるWebアプリケーションで、通常のお知らせ、メンテナンス情報、障害情報の三種類のお知らせを表示させるために
class InformationsController < ApplicationController
def index
end
def maintenance
end
def trouble
end
end
ようなコントローラーを作成したとします。規則性のないメソッド名やコントローラーの肥大化など問題に発展しやすいです。
そこで、DHHはどのようにRailsのコントローラを書くのかの記事では、DHH流のルーティングを学ぶことで、本問題の解決法が提示されています。このDHH流ルーティングを導入しようとした際に、ハマったことをまとめます。
DHH流ルーティングとは
翻訳記事によると
- RESTの原則に従う場合は、全てのコントローラーで例外なくその原則に従うべき
- 全てのコントローラーでは、デフォルトCRUDの
index
,show
,new
,edit
,create
,update
,destroy
メソッドのみを持つこと - 例えばメールボックの受信一覧とペンディング一覧を閲覧するアクションを持つコントローラーを作る場合は、以下のように
index
とpendings
アクションを作るのではなく、
class InboxesController < ApplicationController
def index
end
def pendings
end
end
index
という単一のメソッドだけを持つInboxes::PendingsController
を作成する。これにより独自のスコープとフィルターを提供することができるようになる。
class InboxesController < ApplicationController
def index
end
end
class Inboxes::PendingsController < ApplicationController
def index
end
end
ルーティングを設定する
先程の InboxesController
と Inboxes::PendingsController
を実現するため、以下3パターンを試しました。
resourcesのネスト
resources :inboxes, only: [:index] do
resources :pendings, only: [:index]
end
$ 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
でネストさせます。
resources :inboxes, only: [:index]
namespace :inboxes do
resources :pendings, only: [:index]
end
$ 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指定
resources :inboxes, only: [:index] do
resources :pendings, only: [:index], module: 'inboxes'
end
$ 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オプションを利用することで、簡単に導入することができ、その結果
- 責務に応じたコントローラー分割
- シンプルなコードの実現
という効果が得られるので、積極的に取り入れていきたいです。