DHH流 コントローラーを分割する
DHHについて
DHHはどのようにRailsのコントローラを書くのかを参考に、コントローラーの書き方を変更することにしました。
自分の作ったコントローラの状態を悔やむのは決まって、作ったコントローラの数が少なすぎた時です。多くの処理を任せようとしすぎてしまうんです。
これを実行するのに私が用いているヒューリスティクスはこうです。コントローラが元々持っているRESTアクションやデフォルトの5つの機能にはないメソッドを付け加えたいと思ったら、いつだって新しいコントローラを作る。それだけでいいのです。
ポイント
コントローラーを分割する
今回以下のようなUsersController
を分割することにしました。
class UsersController < ApplicationController def index end def show end def following end def followers end end
デフォルトアクション(CURD)以外のfollowing
とfollowers
はこのように分割できます。↓
# controllers/users_controller.rb class UsersController < ApplicationController def index end def show end end
# controllers/users/followings_controller.rb class Users::FollowingsController < ApplicationController def index end end
# controllers/users/followers_controller.rb class Users::FollowersController < ApplicationController def index end end
ルーティング
今回Users::FollowingsController
のルーティングを考えるにあたり、先にFollowingsController
だった場合について考えます。
FollowingsController
この時の階層はcontrollers/followingsで、ルーティングは以下のようになります。
resources users do resources followings end
パスは、users/:id/followings
を認識します。
Users::FollowingsController
一方今回の階層はcontrollers/users/followingsです。その時ルーティングは以下のようになります。
resources users do resources followings, controller: 'users/followings' end
パスは同じく、users/:id/followings
を認識します。
controllerオプション
controller: 'users/followings'
では、使用するコントローラーを指定しています。
パスはusers/:id/followings
を認識しますが、今回コントローラーはusers/followings
になるので、そちらを指定しています。
名前空間について
名前空間は以下のような構成になっています。
class Hoge TEXT = ... end Hoge::TEXT
Zeitwerk::NameError
名前空間を利用する上で不適切な箇所に(controllers配下に)ファイルを配置していたため、このようなエラーに遭遇しました。
NameError: expected file /app/~~~ to define constant Controller, but didn't
Railsガイドには、以下のように書かれています。
Railsアプリケーションで使うファイル名は、そこで定義されている定数名と一致しなければなりません。ファイル名はディレクトリ名と合わせて名前空間として振る舞います。 たとえば、app/helpers/users_helper.rbファイルではUsersHelperを定義すべきですし、app/controllers/admin/payments_controller.rbではAdmin::PaymentsControllerを定義すべきです。 Railsは、ファイル名をString#camelizeで活用するようZeitwerkを設定します。たとえば、app/controllers/users_controller.rbは以下のためにUsersControllerという定数を定義します。 "users_controller".camelize # => UsersController
具体的には以下のようなことです。
api/users_controller.rb Api::UsersController API::UsersController <= こっちはダメ
またこのルールにそぐわない名前をつけたければ、inflectionsに指定する方法もあるようです。
カスタマイズする必要が生じた場合(略語を追加するなど)は、config/initializers/inflections.rbをチェック