著名なオープンソースRailsアプリのapp/以下を見る
app/
とは
Railsにおける app/
はRailsのアプリケーション用ディレクトリで、普通のRailsアプリケーションでは、この下にmodels
,controllers
,views
を含めた様々なディレクトリが作られます。
基本的には新しいディレクトリを追加する必要はないのですが、アプリケーションが複雑になると、Railsを拡張するべくここにアプリケーション固有のディレクトリを作って、その下に関連するファイルを置くことがあります。
中には、services
やserializers
のように、多くのRailsアプリケーションで見られるものもあれば、完全にアプリケーション独自のものが作られることもあります。また、アプリケーションによっては独自のディレクトリは一切作らないものもあれば、大量に作るものもあります。それぞれアプリケーションの開発方針によるものです。
本記事では、比較的有名なOSSのRailsアプリケーションについて、そのapp/以下がどうなっているかを概観します。
RubyGemsOrg
RubyGemsを集約・配布するためのサイトです。
app/の構成
- assets
- controllers
- helpers
- jobs
- mailers
- middleware
- models
- views
Railsアプリとして標準の構成に忠実な、今風のディレクトリ構成になっています。
唯一の拡張は middleware
です。これはRedirector
というRackのmiddlewareが置かれています。
Redmine
Railsの初期から現在まで開発が続けられているプロジェクト管理用アプリケーションです。
app/の構成
- controllers
- helpers
- models
- views
これは少ないですね…。昔ながらのRailsのapp/を守っている構成で、歴史を感じます。
これはこれでメンテしやすいというのはあるのかもしれません。
Discourse
巨大掲示板というか、ディスカッションWebアプリケーションです。
app/の構成
- assets
- controllers
- helpers
- jobs
- mailers
- models
- serializers
- services
- views
これもシンプルな構造ですね。独自のものはserializers
、services
くらいでしょうか。
serializers
以下にあるのはActiveModel::Serializer
のサブクラスで、モデルのシリアライズ用に使われます。
services
はいわゆるサービスクラス用のディレクトリです。Discourseのサービスクラスは、特に共通のスーパークラスもなく、PORO(Plain Old Ruby Objects)というか、単なるRubyのクラスになっています。メソッドもあまりルールがなく、たくさん生えています。
Diaspora
Facebook等のSNSから離脱(diaspora)するための高機能SNSアプリケーションです。
app/の構成
- assets
- controllers
- helpers
- mailers
- models
- presenters
- serializers
- services
- uploaders
- views
- workers
presenters
、serializers
、services
、workers
辺りが独自ディレクトリでしょうか。
presenters
は主にコントローラーからJSONを吐くために呼ばれるものです。一方、serializers
はActiveModel::Serializer
のサブクラスで、export用などに使われています。
services
はサービスクラス用のディレクトリで、こちらもシンプルなPOROのクラスが置かれています。
workers
はSidekiq用のものです。ここにあるクラスは、Sidekiq::Worker
モジュールなどがincludeされたWorkers::Base
クラスのサブクラスになっています。
Mastodon
分散SNSとして人気を誇るmastodonです。
app/の構成
- chewy
- controllers
- helpers
- javascript
- lib
- mailers
- models
- policies
- presenters
- serializers
- services
- validators
- views
- workers
比較的ディレクトリを多めに作っていますが、役割は明確になっています。
chewy
はElasticsearch用のディレクトリのようです。
また、assetsが廃止され、javascriptがapp/直下に来ているのも特徴的です。libもroot直下のlibとは別にapp/lib
が作られていて、こちらにはapp用のPOROのクラスが置かれています。
policies
以下のクラスはApplicationPolicy
を継承しています。各機能に必要な権限があるかどうかを返すメソッドが実装されています。
services
以下のクラスはBaseServiceクラスを継承する形になっています。基本的にcall
メソッドのみを公開するようになっていて、使う側としては使い方が明確になっています。
validators
以下のクラスはActiveModel::Validatorを継承しています。
validate()
またはvalidate_each()
を公開しています。
workers
もSidekiq用です。
GitLab
GitLabはGitHub的なDevOps用ツールで、GitレポジトリのホスティングにCIが標準でついているのが特長です。
app/の構成
- assets
- channels
- controllers
- finders
- graphql
- helpers
- mailers
- models
- policies
- presenters
- serializers
- services
- uploaders
- validators
- views
- workers
GitLabはドキュメントに力を入れており、独自の固有ディレクトリにもREADME.mdが置かれていて分かりやすくなっていたりします(全てのディレクトリではないです)。
他のアプリケーションでも見られるディレクトリが多いですが、graphql
があるのが今風ですね。
finders
はモデルだけに依存しない検索用メソッドをクラスとして切り出すものです。これにより、モデルを薄くできます。
presenters
はViewに関するロジックやデータのためのクラスを置くためのディレクトリです。これもモデルの肥大化を防ぐためのものです。
serializers
ですが、GitLabではGrapeのGrape::Entity
を使っています。Grape::Entity
を継承したクラスが置かれています。
policies
については、GitLabはDeclarativePolicy frameworkを使っています。こちらを使った権限管理のクラスが置かれています。
uploaders
はアップロードライブラリのCarrierWave用のディレクトリです。このディレクトリ内の各クラスは、直接CarrierWave::Uploader::Base
クラスは継承せず、GitlabUploadersを経由するようにしています。
Forem
foremの名前は知らない方も多いかと思いますが、これはdev.toの本体です。
app/の構成
- assets
- black_box
- controllers
- dashboards
- decorators
- errors
- fields
- helpers
- javascript
- labor
- lib
- liquid_tags
- mailers
- middlewares
- models
- policies
- queries
- sanitizers
- serializers
- services
- uploaders
- view_objects
- views
- workers
見ての通り、大量にディレクトリが導入されています。中には black_box
のように1ファイルだけあるものがあったりします。
他のRailsアプリで見慣れたものも多いものの、具体的にどういう基準でディレクトリを追加しているのかについてはドキュメントを見てもよくわからなかったので、各位頑張って調べて欲しい…という気持ちです。
まとめ
app/直下だけをとっても、アプリケーションごとに様々な方針があるのが垣間見ることができたように思います。
拡張の方針はさておき、GitLabは固有の拡張ディレクトリにはREADME.mdでその内容を説明していて、理解が大変はかどりました。これは真似をするといいのではないでしょうか。
日々のRailsアプリ開発の参考になれば幸いです。
Discussion
@takahashim さん
まとまっていて助かりました!ありがとうございます。