Skip to content

フォルダ構成

Railsのフォルダ構成は、**MVC(Model-View-Controller)**の原則に基づいており、開発者がファイルを探しやすく、またアプリケーションの役割を理解しやすくなるよう設計されています。

以下は、主要なフォルダとその役割です。

.
├── app # アプリケーションの核となるコードを格納
│ ├── assets # スタイルシート、JavaScript、画像などの静的ファイル
│ │ ├── config
│ │ ├── images
│ │ ├── javascript
│ │ └── stylesheets
│ ├── channels # Action Cable(WebSocket)関連のファイルを格納
│ ├── controllers # ユーザーからのリクエストを処理するコントローラー
│ ├── helpers # ビューで使用するヘルパーモジュール
│ ├── jobs # Active Jobによるバックグラウンドジョブ
│ ├── mailers # メール送信のためのクラス
│ ├── models # アプリケーションのデータとビジネスロジックを扱うモデル
│ └── views # ユーザーインターフェース(HTMLなど)を生成するビューテンプレート
├── bin # 実行可能なスクリプト
│ ├── bundle
│ ├── rails # Railsコマンドの実行スクリプト
│ └── rake # Rakeタスクの実行スクリプト
├── config # アプリケーション全体の設定ファイル
│ ├── environments # 開発、テスト、本番など、環境ごとの設定
│ ├── initializers # アプリケーション起動時に実行されるカスタム設定
│ ├── locales # I18n(国際化)のための翻訳ファイル
│ ├── application.rb # アプリケーション全体のコア設定
│ ├── database.yml # データベース接続設定
│ └── routes.rb # URLとコントローラーを結びつけるルーティング定義
├── db # データベース関連のファイル
│ ├── migrate # データベーススキーマを変更するマイグレーションファイル
│ └── seeds.rb # データベースに初期データを投入するためのファイル
├── lib # アプリケーション全体で共有される独自のライブラリ
├── log # アプリケーションのログファイル
├── public # ウェブサーバーから直接アクセス可能な静的ファイル
├── test # テストファイル
├── tmp # 一時ファイル
├── vendor # 外部から取得したベンダー依存のコード
└── Gemfile # プロジェクトの依存関係(Gem)を管理

アプリケーションの核となるコードが置かれるフォルダです。MVCの各コンポーネントがこの中にあります。

  • app/controllers: リクエストを処理するコントローラーのコードを格納します。
  • app/models: アプリケーションのデータとビジネスロジックを扱うモデルのコードを格納します。
  • app/views: ユーザーインターフェース(HTMLやCSSなど)を生成するビューのテンプレートを格納します。
  • app/assets: スタイルシート(CSS)、JavaScript、画像などのアセットファイルが置かれます。

実行可能なスクリプトが格納されるフォルダです。

  • bin/rails: Railsコマンドを実行するためのスクリプト。
  • bin/rake: Rakeタスク(データベースのマイグレーションなど)を実行するためのスクリプト。

アプリケーションの設定ファイルが格納されるフォルダです。

  • config/routes.rb: アプリケーションのルーティング(URLとコントローラーのアクションの紐付け)を定義します。
  • config/database.yml: データベースの接続設定を定義します。
  • config/environments: 開発、テスト、本番など、各環境ごとの設定を定義します。

データベースに関連するファイルが格納されます。

  • db/migrate: データベースのスキーマを変更するためのマイグレーションファイルが置かれます。
  • db/schema.rb: 現在のデータベーススキーマの構造を記録したファイルです。

⚠️ 重要な警告: db/schema.rbは触ってはいけない

Section titled “⚠️ 重要な警告: db/schema.rbは触ってはいけない”

db/schema.rbは、Railsが自動生成するファイルであり、手動で編集してはいけません

初心者がDB構造を変えようとしてschema.rbを直接書き換えてしまうと、マイグレーションファイルと不整合が起きて環境が壊れるのは「Railsあるある」です。

正しいアプローチ:

  • DB構造の変更は必ずdb/migrate内のマイグレーションファイルで行う
  • schema.rbは、マイグレーション実行の結果が反映されるだけの「鏡」である
  • schema.rbをGitにコミットすることで、チーム全体で同じDB構造を共有できる
Terminal window
# 正しい方法: マイグレーションファイルを作成
bundle exec rails generate migration AddTitleToArticles title:string
# マイグレーションを実行すると、schema.rbが自動更新される
bundle exec rails db:migrate

アプリケーションをDockerコンテナとして動かすための設定ファイルです。本番環境でのデプロイを想定して作成されます。

アプリケーション全体で共有されるライブラリやモジュールを格納するフォルダです。

⚠️ libappの使い分けの注意点

Section titled “⚠️ libとappの使い分けの注意点”

初心者は「どこに書けばいいか分からないロジック」をすべてlibに放り込みがちですが、注意が必要です。

重要な違い:

  • app配下のディレクトリ: Railsによって自動読み込み(Autoload)されるため、requireが不要で、開発中のオートリロードも機能する
  • lib配下: 手動でrequireするか、config/application.rbで設定が必要。オートリロードが効かないため、開発効率が下がる

推奨されるアプローチ: ビジネスロジックをlibに書くのではなく、app/servicesapp/logicのような独自のディレクトリをapp内に作って管理することを推奨します。これにより、Railsの仕組みに乗りやすくなり、開発効率が向上します。

app/services/user_registration_service.rb
class UserRegistrationService
def self.call(user_params)
# ビジネスロジック
end
end
# 非推奨: lib/user_registration_service.rb
# (requireが必要で、オートリロードが効かない)

libは、Railsアプリケーションの外部で使用される汎用的なライブラリや、Gem化する予定のコードを置く場所として使用するのが適切です。

アプリケーションのログファイルが格納されます。

ウェブサーバーから直接アクセス可能な静的ファイル(HTML、画像など)を格納します。

アプリケーションのテストファイルが格納されます。

test vs spec: テストフレームワークの選択

Section titled “test vs spec: テストフレームワークの選択”

Railsの標準ではtestフォルダにMinitestのテストファイルを配置しますが、日本のRails現場の多く(約7〜8割以上)は標準のMinitestではなくRSpecを使います

  • test/: Rails標準のMinitestを使用する場合
  • spec/: RSpecを使用する場合(デファクトスタンダード)

実務に入ると、test/フォルダではなくspec/フォルダが存在するケースが圧倒的に多いです。RSpecを使用する場合は、specフォルダにテストファイルを配置します。

test/models/user_test.rb
# test/ の場合(Minitest)
class UserTest < ActiveSupport::TestCase
test "should be valid" do
user = User.new
assert user.valid?
end
end
# spec/ の場合(RSpec)
# spec/models/user_spec.rb
RSpec.describe User, type: :model do
it "should be valid" do
user = User.new
expect(user).to be_valid
end
end

プロジェクトに参加する際は、どちらのテストフレームワークを使用しているか確認しましょう。

外部から取得したベンダー依存のコード(サードパーティライブラリなど)を格納するフォルダです。

⚠️ vendorフォルダの「形骸化」

Section titled “⚠️ vendorフォルダの「形骸化」”

現代のRails開発では、vendorフォルダを使う機会は激減しています。

理由:

  • ほとんどのライブラリはGemfile(Ruby)かpackage.json(JavaScript)で管理される
  • Bundlerやnpmなどのパッケージマネージャーが依存関係を管理する

vendorを使うべきケース:

  • Gem化されていない特殊なプラグインを使う時だけ
  • 外部から取得したコードを直接プロジェクトに含める必要がある場合

重要な注意点:

  • 自作のコードをvendorに置かないこと。自作のコードはapp配下に配置すべきです
  • vendorは「外部から取得したコード」専用のフォルダとして理解しましょう

これらのフォルダは、Railsの「設定より規約」の思想に基づいているため、開発者はファイルを作成する場所を迷うことなく、効率的に開発を進めることができます。

なお、ここからはRails7系以降の解説です。

Rails 7以降、Hotwire(HTML Over The Wire)がデフォルトのフロントエンドアプローチとして採用されました。これは、JavaScriptを最小限に抑え、HTMLを通じてサーバーとやり取りすることで、SPA(Single Page Application)のような高速なユーザー体験を実現するものです。

  • app/javascript/controllers: このディレクトリは、Hotwireの一部であるStimulusのコントローラを格納するために使用されます。Stimulusは、HTMLに直接アクションやターゲットを記述することで、JavaScriptの振る舞いをカプセル化し、再利用可能なコンポーネントを作成できます。

2. Propshaftとアセットパイプラインの進化

Section titled “2. Propshaftとアセットパイプラインの進化”

Rails 7では、従来のSprocketsに代わる新しいアセットマネジメントツールとしてPropshaftが導入されました。Propshaftは、CSSやJavaScriptのトランスパイルやバンドルをよりシンプルかつ高速に行うことを目的としています。

  • app/assets ディレクトリの役割は変わりませんが、内部的な処理がPropshaftに置き換わることで、ビルドのパフォーマンスが向上します。

Rails 7では、Importmapを使用してJavaScriptの依存関係を管理する方法が標準となりました。これにより、開発者はnpm installを使わずに、ブラウザが直接ESモジュールをロードできるようになります。

  • config/importmap.rb: このファイルは、各JavaScriptモジュールをURLにマッピングするために使用されます。これにより、フロントエンドの依存関係をNode.jsなしで管理できます。

⚠️ app/javascriptとReactの共存問題

Section titled “⚠️ app/javascriptとReactの共存問題”

Rails 7でimportmapがデフォルトになりましたが、Reactを使う場合は話が変わります

問題点:

  • ReactやTypeScriptを本格的に使う場合、importmapではライブラリの依存解決やJSXのコンパイルが困難です
  • importmapはESモジュールを直接ロードする仕組みであり、トランスパイルやバンドルが必要なReactには不向きです

解決策: jsbundling-railsの使用

Reactを使うプロジェクトでは、結局jsbundling-rails(esbuild/webpack)を選ぶことになります。

Terminal window
# jsbundling-railsとesbuildを追加
bundle add jsbundling-rails
bundle exec rails javascript:install:esbuild

この場合、フォルダ構成はapp/javascript内にReactコンポーネントが並ぶ独自の構成になります:

app/javascript/
├── application.js # エントリーポイント
├── components/ # Reactコンポーネント
│ ├── Header.jsx
│ └── Footer.jsx
└── utils/ # ユーティリティ関数

選択の指針:

  • Hotwire/Stimulusのみ: importmapで十分
  • React/TypeScriptを本格使用: jsbundling-rails(esbuild/webpack)が必要

プロジェクトの要件に応じて、適切なアプローチを選択しましょう。

これらの変更点は、Railsの最新のトレンドを反映しており、特にフロントエンド開発におけるアプローチに大きな影響を与えています。このドキュメントにこれらのトピックを追加することで、Railsの進化を捉えた、より現代的で実践的な内容になります。