3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

第0章|今さら学ぶ「全体像」

3
Last updated at Posted at 2026-02-17

第0章|今さら学ぶ「全体像」

📚 シリーズ目次はこちら → 「今さら学ぶ」シリーズ — はじめに

この章でわかること

  • Webアプリが動く全体の仕組み(リクエスト → レスポンスの流れ)
  • 「ブラウザでURLを打ってからページが表示されるまで」に何が起きているか
  • MVCとは何か — なぜ「分ける」ことが大事なのか(技術的な定義)
  • MVC・ルーティング・DBがどう連携しているか
  • エラーメッセージの読み方 — 「どこで → 何が → なぜ」の3ステップ

🏠 たとえ話で掴む「Webアプリの全体像」

Webアプリの仕組みは、 宅配ピザの注文 にたとえると整理しやすい。

スマホでピザを注文する場面を思い浮かべてほしい。

宅配ピザ Webアプリ
スマホの注文アプリ ブラウザ (Chrome等)
「マルゲリータ1枚」と注文 リクエスト (GET /articles/1)
コールセンター(注文の振り分け) ルーティング
店長(指示を出す人) コントローラ
ピザ職人 + 材料棚 モデル + データベース
ピザを箱に入れて梱包 ビュー(HTML)
バイクで届く レスポンス

流れはこうなる。

  1. スマホで注文する → ブラウザがURLにアクセスする(リクエスト)
  2. コールセンターが受け付ける → ルーティングが「どのコントローラのどのアクションか」を振り分ける
  3. 店長がピザ職人に伝える → コントローラがモデルにデータを要求する
  4. ピザ職人が材料棚から取り出して焼く → モデルがDBからデータを取得して加工する
  5. ピザを箱に詰める → ビューがHTMLを組み立てる
  6. バイクでお届け → ブラウザにレスポンスが返る

これがWebアプリの「リクエスト → レスポンス」の全体像です。Railsの学習で触れてきたことは全部、この流れのどこかに当てはまります。


🏗️ MVCとは何か — 技術的な定義

MVCはスクールで必ず出てくるが、面接で「MVCの各層の責務を説明してください」と聞かれると意外と詰まる。自分もそうでした。改めて整理してみると、ポイントは 「責務の分離」 でした。

宅配ピザのたとえで「店長」「ピザ職人」「梱包担当」と役割が分かれていたように、この 「役割を分ける」設計の考え方 を、技術的には MVC(Model-View-Controller)パターン と呼びます。

MVCは1970年代にSmalltalkというプログラミング言語の中で生まれた、歴史のある デザインパターン(設計の定石) です。では、なぜ「分ける」必要があるのか。

もしMVCがなかったら

# ❌ MVCがない世界 — 1つのファイルに全部入り
# (実際にこう書くわけではないが、イメージとして)

if request.path == "/articles/1"
  # --- DB接続 ---
  db = PG.connect(dbname: "knowledgenote")
  result = db.exec("SELECT * FROM articles WHERE id = 1")
  article = result.first

  # --- HTML組み立て ---
  html = "<html><body>"
  html += "<h1>#{article['title']}</h1>"
  html += "<p>#{article['body']}</p>"
  html += "</body></html>"

  # --- レスポンス ---
  [200, { "Content-Type" => "text/html" }, [html]]
end

たった1ページ分のコードで、もう問題が見えてくる。

  • タイトルの表示を変えたいだけなのに、DB接続のコードと同じファイルを触る必要がある
  • 「記事一覧」ページを追加するとき、DB接続のコードをコピペすることになる
  • ファイルが1,000行を超えたら、どこに何があるか誰もわからなくなる

つまり 変更のたびに関係ない部分まで壊すリスクがある。これが「全部入り」の最大の問題です。

MVCの3つの層 — 「責務の分離」

MVCは、この問題を 「責務の分離(Separation of Concerns)」 で解決する。プログラムを3つの層に分けて、それぞれに明確な役割を持たせます。

層 正式な責務 やること やらないこと
Model (モデル) ビジネスロジックとデータの永続化 データの取得・保存・加工・バリデーション HTMLの組み立て、リクエストの受付
View (ビュー) ユーザーへの情報の表示 HTMLの組み立て、データの見せ方の整形 DB問い合わせ、ビジネスロジック
Controller (コントローラ) リクエストの受付と橋渡し リクエストを受け取り、Modelに頼み、Viewに渡す 自分でデータを加工する、自分でHTMLを組み立てる

大事なのは 「やらないこと」 の列です。各層は自分の責務以外のことをしない。この制約があるからこそ、「デザインを変えたい → Viewだけ触ればいい」「バリデーションを追加したい → Modelだけ触ればいい」と、変更の影響範囲を限定できます。

なぜMVCが面接で必ず聞かれるのか

MVCの本当の価値は、 「変更に強いコードになる」 ことです。

Webアプリは完成したら終わりではありません。機能追加、デザイン変更、バグ修正…実務では日々変更が入ります。MVCで責務を分けてあれば、変更を局所化できる。だからチーム開発では必須の考え方とされています。

逆にMVCを守らず、コントローラにビジネスロジックを詰め込んでしまう状態を Fat Controller(太ったコントローラ) と呼びます。

# ❌ Fat Controller — コントローラがやりすぎ
class ArticlesController < ApplicationController
  def index
    @articles = Article.where(status: "published")
                       .where("created_at > ?", 30.days.ago)
                       .order(likes_count: :desc)
    # ↑ 本来はModelの仕事(どの記事を「人気」とするかはビジネスロジック)
  end
end

# ✅ Modelに責務を移す
class Article < ApplicationRecord
  scope :popular_recent, -> {
    where(status: "published")
      .where("created_at > ?", 30.days.ago)
      .order(likes_count: :desc)
  }
end

class ArticlesController < ApplicationController
  def index
    @articles = Article.popular_recent  # コントローラはModelに頼むだけ
  end
end

Fat Controllerは実務で最もよく見かけるアンチパターンの1つです。「MVCを知っている」と「MVCを守れる」は別の話で、この違いがわかっていると、コードレビューでも的確に指摘できるようになります(→ 第25章で詳しく扱います)。


🔄 もう少し技術的に:リクエストからレスポンスまでの旅

宅配ピザのたとえとMVCの定義を踏まえて、Railsアプリの実際の流れを追ってみます。

KnowledgeNoteで「記事の詳細ページを開く」場合の例です。

ステップ1:ブラウザがリクエストを送る

ユーザーが記事のリンクをクリックすると、ブラウザは次のようなリクエストをサーバに送ります。

GET /articles/1 HTTP/1.1
Host: knowledgenote.example.com

これは「/articles/1 のページをちょうだい(GET)」という意味です。HTTPメソッド(GET / POST / PATCH / DELETE)については第6章で詳しく扱いますが、ここでは「GETは『見せて』という要求」程度の理解で大丈夫です。

ステップ2:ルーティングが振り分ける

リクエストがRailsサーバに届くと、最初に仕事をするのが ルーティング です。

# config/routes.rb
resources :articles

この1行で、Railsは「GET /articles/1 は ArticlesController の show アクションだな」と自動で判断します。宅配ピザのコールセンターが「マルゲリータ → 渋谷店のピザ担当へ」と振り分けるのと同じ役割です(→ 第10章で詳しく扱います)。

ステップ3:コントローラが指示を出す

ルーティングに指名されたコントローラが動きます。

# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
  def show
    @article = Article.find(params[:id])  # モデルにデータを要求
  end
end

コントローラは自分でピザは焼かない。 「id=1の記事を持ってきて」とモデルに頼む のが仕事です。宅配ピザでいう店長と同じで、自分で生地をこねることはしません。

ステップ4:モデルがDBからデータを取得する

モデル(Article)がデータベースに問い合わせます。

# 裏側で実行されるSQL
SELECT * FROM articles WHERE id = 1;

データベースは「材料棚」です。必要な材料(データ)を取り出して、モデルが受け取る。モデルはただ取り出すだけでなく、 バリデーション(材料の品質チェック) や アソシエーション(関連する材料も一緒に取り出す) も担当しています(→ 第12章、第15章で詳しく扱います)。

ステップ5:ビューがHTMLを組み立てる

コントローラが受け取ったデータを、ビューに渡します。

<!-- app/views/articles/show.html.erb -->
<h1><%= @article.title %></h1>
<p><%= @article.body %></p>
<span>by <%= @article.user.name %></span>

ビューは「梱包担当」です。データをHTMLという「ピザ箱」にきれいに詰める。<%= %> の中にRubyのコードを書けるのがERBの特徴です(→ 第13章で詳しく扱います)。

ステップ6:レスポンスがブラウザに届く

完成したHTMLがブラウザに届き、ユーザーの画面に記事が表示されます。

HTTP/1.1 200 OK
Content-Type: text/html

<html>
  <body>
    <h1>Railsのルーティングを完全理解する</h1>
    ...
  </body>
</html>

ここまでの所要時間は、だいたい 数十ミリ秒〜数百ミリ秒。一瞬で「注文→調理→配達」が完了しています。


📍 全体像マップ:Railsで学んだことの「位置」

ここまでの流れを図にすると、こうなります。

ブラウザ                         Railsサーバ
┌──────┐    リクエスト     ┌────────────────────────────────┐
│      │  ────────────>  │  ルーティング(config/routes.rb)│
│      │                 │       │                        │
│      │                 │       ▼                        │
│      │                 │  コントローラ(app/controllers/)│
│      │                 │    ↓依頼         ↑データ受取   │
│      │                 │  モデル(app/models/)           │
│      │                 │    ↓SQL照会      ↑結果返却      │
│      │                 │  データベース(SQLite/PostgreSQL)│
│      │                 │       │                        │
│      │                 │       ▼(コントローラ経由)     │
│      │   レスポンス     │  ビュー(app/views/)           │
│      │  <────────────  │                                │
└──────┘                 └────────────────────────────────┘

Rails学習で触れてきた内容は、すべてこの図のどこかに位置しています。

図の位置 やったこと このシリーズでの章
ルーティング resources でURL自動生成 第10章
コントローラ before_action でアクセス制限 第14章
モデル has_many で関連付け 第15章
データベース マイグレーションでテーブル作成 第16,18章
ビュー ERBでデータを画面に表示 第13章
リクエスト全般 Turbo Streamsで部分更新 第19章

「あの時やったあれ、全体のここだったのか」と繋がれば、この章の役割は果たせています。


🔍 「遅い」「エラー」のとき、どこを疑うか

全体の流れがわかっていると、 トラブルシューティングが格段に楽になります。

問題が起きたとき、「宅配ピザのどの工程で詰まっているか」で切り分けられる。

パターン①:ページが表示されない(エラー)

ルーティングエラー → 注文が通っていない → routes.rbを確認
    例:No route matches [GET] "/artcles/1"(スペルミス)

コントローラエラー → 店長が混乱 → コントローラを確認
    例:NameError: undefined local variable 'artcle'

モデルエラー → 材料が見つからない → モデル/DBを確認
    例:ActiveRecord::RecordNotFound(id=999の記事が存在しない)

ビューエラー → 梱包に失敗 → ビューテンプレートを確認
    例:NoMethodError: undefined method 'name' for nil:NilClass

パターン②:ページは出るけど遅い

DBが遅い → 材料棚が散らかっている
    → インデックスが足りない?N+1問題?(→ 第17章)

コントローラが遅い → 店長が余計な仕事をしている
    → 不要なクエリを投げていないか?(→ 第24章)

ビューが遅い → 梱包が複雑すぎる
    → パーシャルのループが多すぎないか?(→ 第24章)

実践:「nilのエラー」を3ステップで切り分ける

一覧だけだとピンとこないので、実際に一番よく遭遇するエラーで切り分けてみる。

ブラウザに赤い画面が出て、こんなエラーメッセージが表示されたとします。

NoMethodError: undefined method 'name' for nil:NilClass

慌てず、3ステップで追いかけます。

① どこで起きたか?(スタックトレースを見る)

エラー画面の下の方に、こんな行が並んでいます。これが スタックトレース(呼び出し履歴) です。

app/views/articles/show.html.erb:3:in `_app_views_articles_show_html_erb__...`
app/controllers/articles_controller.rb:5:in `show`

一番上の行が「エラーが実際に起きた場所」です。show.html.erb の3行目 — つまり ビュー(梱包の工程)で起きた とわかります。

② 何がnilか?(エラーメッセージを読む)

「nil に対して name メソッドを呼んだ」と言っています。3行目を見ると:

<span>by <%= @article.user.name %></span>

@article.user が nil — つまり 「記事に紐づくユーザーがいない」 ということです。

③ なぜnilか?(原因を探る)

ここで考えられる原因はいくつかある。

  • articles テーブルの user_id に存在しないIDが入っていた(外部キー制約の未設定)
  • ユーザーが退会したのにその人の記事が残っていた(dependent: :destroy の未設定)
  • そもそも user_id が nil だった(バリデーションの漏れ)

このように 「どこで → 何が → なぜ」 の順で追いかけると、エラーの原因に最短でたどり着けます(→ 第23章で詳しく扱います)。


💼 面接で聞かれたら?

Q:RailsのMVCについて説明してください。

「MVCはModel・View・Controllerの3つの層に責務を分けるデザインパターンです。Modelはビジネスロジックとデータの永続化、Viewはユーザーへの情報の表示、Controllerはリクエストの受付とModelへの指示・Viewへのデータの受け渡しを担当します。各層の責務を分離することで、変更の影響範囲を限定できます。たとえばデザインを変えたいときはViewだけ、バリデーションを追加したいときはModelだけを修正すればよく、他の層に影響が出にくくなります。」

深掘りされたら:

  • 「なぜ分けるのか?」→ 変更の影響範囲を限定するため。1つのファイルにすべてを書くと、画面修正のつもりでDB処理まで壊すリスクがある。「責務の分離(Separation of Concerns)」という設計原則にもとづいている。
  • 「Fat Controllerとは?」→ Controllerにビジネスロジックを詰め込みすぎた状態。本来Modelがやるべきデータの加工や判定をControllerに書いてしまうこと。MVCの恩恵を自ら捨てているアンチパターン。

🔗 もっと深く知りたい人へ(1次情報リンク)


まとめ

  • ✅ Webアプリは「リクエスト → ルーティング → コントローラ → モデル → DB → ビュー → レスポンス」の流れで動く
  • ✅ MVCは「責務の分離」のデザインパターン。Model(データとロジック)・View(表示)・Controller(橋渡し)に分けることで、変更の影響範囲を限定する
  • ✅ MVCがない世界では、1つの変更が全体を壊すリスクがある。だから分ける
  • ✅ Fat Controllerは、Controllerにビジネスロジックを詰め込んだアンチパターン
  • ✅ エラーは「どこで → 何が → なぜ」の3ステップで追いかけると最短で原因にたどり着ける

📚 シリーズ目次:「今さら学ぶ」シリーズ — はじめに

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?