モジュールを使った名前空間でRailsのコードをリファクタリングする
名前空間とは
名前空間はメソッドや変数の名前が衝突しないように管理するための仕組みで、様々なプログラミング言語で実装されていて、Rubyではモジュールを使って名前空間を実現できます。
module Hoge
class Fuga
def hello
puts "hello namespace"
end
end
end
fuga = Hoge::Fuga.new
fuga.hello
名前空間を活用するとクラス名や名前の衝突を防ぐほかに、
関連するクラスやメソッドを特定のフォルダにまとめることで、プロジェクト全体の構造を把握しやすくなります。
Rails内部で利用されている機能例としては ActionMailer::Base
や ActiveRecord::Base
などが挙げられます。
ここからは、Railsで名前空間を使う具体例を交えながら、そのメリットについて説明していきます。
モデルやクラスを整理する
名前空間を利用してディレクトリを作成し、モデルやクラスを集約することができます。
PaymentProcess
、PaymentRefund
というクラス名を Payment::Process
と Payment::Refund
することができ、ディレクトリ構成についても下記のように整理が可能です。
before
app/
└── models/
├── payment_process.rb
└── payment_refund.rb
after
app/
└── models/
└── payment/
├── process.rb
└── refund.rb
このように関連するクラスをひとまとめに整理することで、
多くのクラスが増えてきたときに階層化しておくことでPaymentに関わるModelを見つけるのが容易になります。
Controllerを整理する
Controllerでも名前空間を使ってコードをリファクタリングすることが可能です。
下記のように管理者用の画面を実装する場合に、Adminという名前空間の配下にControllerを作っておくと見通しが良くなります。
class Admin::StaffsController < Admin::ApplicationController
def index
# ...
end
end
Controllerでもディレクトリ構造もこのようになります。
app
└── controllers/
├── admin/
│ ├── application_controller.rb
│ └── staffs_controller.rb
├── application_controller.rb
└── users_controller.rb
Viewファイルも下記のような構造になっています。
└── views/
├── admin/
│ └── staffs/
│ └── index.html.erb
└── users/
├── _form.html.erb
├── _user.html.erb
├── index.html.erb
└── show.html.erb
管理者(Admin)用のControllerを作る
Admin::ApplicationController
を作って継承することで、
管理者用Controllerの共通処理をAdmin::ApplicationControllerにまとめておくことが可能です。
ルーティングについても下記のように定義することで対応可能です。
Rails.application.routes.draw do
namespace :admin do
resources :staffs
end
end
デメリット
名前空間を使いすぎるとディレクトリが深くなりすぎて、コードの見通しが悪くなるため、2〜3階層にとどめることをお勧めします
app/
└── models/
└── user/
└── comment
└── response
└── image.rb
モジュールが使えないケース
Railsでは自動でクラスを読み込む仕組みがあり、モジュール名と同じ名前のクラスがすでに存在しているとエラーが発生することがあります。
このときはモジュールは利用できないので下記のように定義しましょう。
class User::Session
def initialize(user)
@user = user
end
def create!
# ...
end
end
User::Session.new(user).create!
まとめ
名前空間を使ってモデルやControllerを整理する事例を紹介しました。
モデルやControllerの整理が容易になり、クラス名が長くなりすぎることを防げます。ディレクトリ構造が整理されることで、クラス間の関係性も把握しやすくなります。弊社でもこの方法を積極的に活用しており、基本的な内容ではありますがリファクタリングの参考となれば幸いです。
Discussion