Rails アンチパターン - モノリシックなコントローラ(Monolithic Controllers)

引き続きRails AntiPatternsという本を読んでいます。

https://www.amazon.co.jp/dp/B004C04QE0/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

前回は7 Testの1つめ「Fixture Blues」についてまとめました。

waterlow2013.hatenablog.com   今回は4 Controllersの4つめ「Monolithic Controllers」についてまとめます。

Monolithic Controllers

解決策有りきなのだが、REST原則に乗っていないコントローラをRESTに乗せる。 以下のようなサンプルがあったとする。

class AdminController
  def users
    #...
    if not params[:operation].nil?
      if params[:operation] == "reset_password"
        # ...
      end
      if params[:operation] == "activate_user"
        #...
      end
      if params[:operation] == "show_user"
        #...
      end
    end
    user_order = 'username'
    if not params[:user_sort_field].nil?
      user_order = params[:user_sort_field]
      # ...
    end
  end
end

URLは以下になります。

POST /admin/users?operation=reset_password?id=x
POST /admin/users?operation=delete_user?id=x
POST /admin/users?operation=activate_user?id=x
GET /admin/users?operation=show_user?id=x
GET /admin/users

usersはアクションではなくリソース名であるべきなのでうつす。また、operationの中身をアクションに移動する。 urlは以下のように変わる。

POST /admin/users/:id/password
DELETE /admin/users/:id
POST /admin/users/:id/activation
GET /admin/users/:id
GET /admin/users

コードも変わる

class UsersController < ApplicationController
  def index
    # ...
  end

  def destroy
    # ...
  end

  def show
    # ...
  end
end

class PasswordsController < ApplicationController
  def create
    # ...
  end
end

class ActivationsController < ApplicationController
  def create
    # ...
  end
end

config/routes.rbは以下のようになる。

namespace :admin do
  resources :users do
    resource :passwords
    resource :activations
  end
end

まとめ

index, new, create, edit, update, show, destroy以外のアクションがある場合や、アクションが7つに含まれていても1つのアクションが大きくなっている場合はRESTに寄せつつコントローラを分け、先に書いた7つのアクションに乗せるのがいいと思います。

DHHのコントローラの作り方の記事にも書いてましたね! postd.cc