🛤️

著名なオープンソースRailsアプリのapp/以下を見る

2020/10/11に公開1

Railsにおける app/ とは

app/はRailsのアプリケーション用ディレクトリで、普通のRailsアプリケーションでは、この下にmodels,controllers,viewsを含めた様々なディレクトリが作られます。

基本的には新しいディレクトリを追加する必要はないのですが、アプリケーションが複雑になると、Railsを拡張するべくここにアプリケーション固有のディレクトリを作って、その下に関連するファイルを置くことがあります。

中には、servicesserializersのように、多くのRailsアプリケーションで見られるものもあれば、完全にアプリケーション独自のものが作られることもあります。また、アプリケーションによっては独自のディレクトリは一切作らないものもあれば、大量に作るものもあります。それぞれアプリケーションの開発方針によるものです。

本記事では、比較的有名なOSSのRailsアプリケーションについて、そのapp/以下がどうなっているかを概観します。

RubyGemsOrg

https://github.com/rubygems/rubygems.org

RubyGemsを集約・配布するためのサイトです。

app/の構成

  • assets
  • controllers
  • helpers
  • jobs
  • mailers
  • middleware
  • models
  • views

Railsアプリとして標準の構成に忠実な、今風のディレクトリ構成になっています。

唯一の拡張は middleware です。これはRedirectorというRackのmiddlewareが置かれています。

Redmine

https://www.redmine.org/projects/redmine/repository/show/trunk
https://github.com/redmine/redmine

Railsの初期から現在まで開発が続けられているプロジェクト管理用アプリケーションです。

app/の構成

  • controllers
  • helpers
  • models
  • views

これは少ないですね…。昔ながらのRailsのapp/を守っている構成で、歴史を感じます。
これはこれでメンテしやすいというのはあるのかもしれません。

Discourse

https://github.com/discourse/discourse

巨大掲示板というか、ディスカッションWebアプリケーションです。

app/の構成

  • assets
  • controllers
  • helpers
  • jobs
  • mailers
  • models
  • serializers
  • services
  • views

これもシンプルな構造ですね。独自のものはserializersservicesくらいでしょうか。

serializers以下にあるのはActiveModel::Serializerのサブクラスで、モデルのシリアライズ用に使われます。

servicesはいわゆるサービスクラス用のディレクトリです。Discourseのサービスクラスは、特に共通のスーパークラスもなく、PORO(Plain Old Ruby Objects)というか、単なるRubyのクラスになっています。メソッドもあまりルールがなく、たくさん生えています。

Diaspora

https://github.com/diaspora/diaspora

Facebook等のSNSから離脱(diaspora)するための高機能SNSアプリケーションです。

app/の構成

  • assets
  • controllers
  • helpers
  • mailers
  • models
  • presenters
  • serializers
  • services
  • uploaders
  • views
  • workers

presentersserializersservicesworkers辺りが独自ディレクトリでしょうか。

presentersは主にコントローラーからJSONを吐くために呼ばれるものです。一方、serializersActiveModel::Serializerのサブクラスで、export用などに使われています。

servicesはサービスクラス用のディレクトリで、こちらもシンプルなPOROのクラスが置かれています。

workersSidekiq用のものです。ここにあるクラスは、Sidekiq::WorkerモジュールなどがincludeされたWorkers::Baseクラスのサブクラスになっています。

Mastodon

https://github.com/tootsuite/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

https://gitlab.com/gitlab-org/gitlab-foss/
https://github.com/gitlabhq/gitlabhq

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ではGrapeGrape::Entityを使っています。Grape::Entityを継承したクラスが置かれています。

policiesについては、GitLabはDeclarativePolicy frameworkを使っています。こちらを使った権限管理のクラスが置かれています。

uploadersはアップロードライブラリのCarrierWave用のディレクトリです。このディレクトリ内の各クラスは、直接CarrierWave::Uploader::Baseクラスは継承せず、GitlabUploadersを経由するようにしています。

Forem

https://github.com/forem/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 さん
まとまっていて助かりました!ありがとうございます。