第10章|今さら学ぶ「ルーティングとRESTfulリソース」
📚 シリーズ目次はこちら → 「今さら学ぶ」シリーズ — はじめに
🗺️ KnowledgeNoteの設計を確認 → 設計マップ
この章でわかること
-
resources :articlesが自動で生む7つのルートの全体像 - RESTful設計とは何か — 「統一されたURLの作法」
-
only:/except:で必要なルートだけ開ける方法 - 名前付きルート(
_path/_url)の仕組み - ネストしたリソースと
member/collectionの使い方
🏠 たとえ話で掴む「ルーティング」
ルーティングは、第0章で「コールセンター」、第6章で「図書館の窓口」にたとえました。今回はもう少し具体的に、 市役所の窓口 で整理します。
市役所に行くと、「住民票の窓口」「戸籍の窓口」「税金の窓口」と目的別に窓口が分かれています。そして各窓口では「発行してほしい(GET)」「届出を出したい(POST)」「変更したい(PATCH)」「取り消したい(DELETE)」といった手続きができます。
Railsの resources は、 1つのリソース(たとえば記事)に対して、必要な窓口を7つまとめて自動で開設する仕組み です。
resources :articles
# ↓ これだけで7つの窓口(ルート)が開く
| 窓口番号 | HTTPメソッド | URL | アクション | 市役所のたとえ |
|---|---|---|---|---|
| ① | GET | /articles |
index |
記事の一覧を見せてください |
| ② | GET | /articles/new |
new |
新しい記事の申請書をください |
| ③ | POST | /articles |
create |
申請書を提出します(新規作成) |
| ④ | GET | /articles/:id |
show |
1番の記事を見せてください |
| ⑤ | GET | /articles/:id/edit |
edit |
1番の記事の変更届をください |
| ⑥ | PATCH | /articles/:id |
update |
変更届を提出します(更新) |
| ⑦ | DELETE | /articles/:id |
destroy |
1番の記事を取り消してください |
たった1行の resources :articles で、これだけの窓口が自動で用意されます。これがRailsの規約の力です。
ルーティングとは何か — 技術的な定義
URLとコントローラを結びつける仕組み
ルーティング(Routing) は、HTTPリクエスト(URLとHTTPメソッドの組み合わせ)を受け取り、それを どのコントローラのどのアクションで処理するか を決定するマッピング機構です。
Webアプリに届くリクエストは、すべて「URL + HTTPメソッド」の組み合わせで表現されます。GET /articles/1 というリクエストが来たとき、Railsのルーターは config/routes.rb の定義を参照して ArticlesController#show を呼び出す、という対応付けを行います。
RESTとは
REST(Representational State Transfer) は、2000年にRoy Fieldingが提唱したWebの設計思想です。RESTでは、Web上のすべてのものを「リソース」として扱い、URLでリソースを特定し、HTTPメソッドで操作の種類を表現します。
Railsの resources メソッドは、このREST設計をRubyのDSL(ドメイン固有言語)として簡潔に表現したものです。1行書くだけで7つのルートが生成される仕組みは、RESTの規約をRailsのCoCに落とし込んだ設計です。
🌐 RESTful設計とは
RESTの基本的な考え方
RESTが提唱する内容は、難しく聞こえますがポイントは1つだけです。
「URLはリソース(もの)を表し、HTTPメソッドで操作を表す」
✅ RESTfulなURL設計
GET /articles → 記事の一覧を取得
POST /articles → 記事を新規作成
GET /articles/1 → 記事1件を取得
PATCH /articles/1 → 記事を更新
DELETE /articles/1 → 記事を削除
❌ RESTfulでないURL設計
GET /getArticleList → URLに動詞が入っている
POST /createNewArticle → 動詞がURL側にある
GET /articles/delete/1 → DELETEなのにGETを使っている
RESTfulな設計では、 URLは「何を」を表し、HTTPメソッドは「どうする」を表す と役割を分けます。この統一ルールに従うことで、URLを見ただけで「何をしているか」がわかります。
なぜRESTfulが大事か
■ 開発者にとって
→ URLの設計で迷わない。「記事の操作なら /articles」と統一
→ チームメンバーがURLを見ただけで処理を推測できる
■ 面接で
→ 「RESTful設計」は頻出質問。resources の7アクションを説明できることが大事
🔧 only: / except: — 必要な窓口だけ開ける
resources は7つのルートを一気に作りますが、全部必要とは限りません。KnowledgeNoteのコメント機能では「作成」と「削除」だけあればいい、という場合もあります。
# 7つ全部開ける
resources :articles
# 必要なものだけ指定(allowlist方式)
resources :comments, only: [:create, :destroy]
# → create と destroy の2つだけ
# 不要なものを除外(denylist方式)
resources :users, except: [:new, :create]
# → new と create 以外の5つ
# onlyの方がよく使われる(何が開いているか明確だから)
市役所にたとえると、「コメント窓口は、提出と取り消しだけ受け付けます。閲覧窓口はありません」ということです。 不要な窓口を開けっぱなしにしない のは、セキュリティの観点でも大切です(→ 第20章で詳しく扱います)。
🏷️ 名前付きルート — URLのニックネーム
resources で生成されるルートには、 名前(ニックネーム) がつきます。URLを直接書く代わりに、この名前を使ってリンクを生成できます。
resources :articles
| ヘルパー名 | 生成されるURL | 使い方 |
|---|---|---|
articles_path |
/articles |
一覧ページへのリンク |
new_article_path |
/articles/new |
新規作成ページへのリンク |
article_path(article) |
/articles/1 |
記事詳細ページへのリンク |
edit_article_path(article) |
/articles/1/edit |
編集ページへのリンク |
_path と _url の違い
article_path(article) # => "/articles/1"(相対パス)
article_url(article) # => "http://localhost:3000/articles/1"(絶対URL)
| ヘルパー | 返すもの | 使いどころ |
|---|---|---|
_path |
/articles/1 |
ビュー内のリンク(ほとんどこちら) |
_url |
http://... |
メール本文内のリンクなど、ドメイン名まで必要な場面 |
普段は _path を使えば十分 です。_url が必要なのは、メール本文にリンクを入れるときなど、ドメイン名まで含む完全なURLが必要な場面です。
なぜ名前付きルートを使うのか
<!-- ❌ URLを直接書く — URLが変わったら全部修正が必要 -->
<a href="/articles/<%= article.id %>">記事を見る</a>
<!-- ✅ 名前付きルートを使う — URLが変わっても1箇所の修正で済む -->
<%= link_to "記事を見る", article_path(article) %>
URL構造を変更しても、ルーティングを1箇所直すだけで、ビュー側の修正が不要になります。これもDRY原則の実践です。
🔀 ネストしたリソース — 部署の中の担当者
KnowledgeNoteでは、コメントは必ず記事に紐づきます。「どの記事のコメントか」をURLで表現するのが ネストしたリソース です。
# config/routes.rb
resources :articles do
resources :comments, only: [:create, :destroy]
end
これにより、以下のルートが生成されます。
| HTTPメソッド | URL | アクション |
|---|---|---|
| POST | /articles/:article_id/comments |
comments#create |
| DELETE | /articles/:article_id/comments/:id |
comments#destroy |
URLを見るだけで「記事3のコメントを作成する」「記事3のコメント5を削除する」という意味がわかります。
# app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def create
@article = Article.find(params[:article_id]) # URLから記事を特定
@comment = @article.comments.build(comment_params)
@comment.user = current_user
if @comment.save
redirect_to @article, notice: "コメントを投稿しました"
else
redirect_to @article, alert: "コメントの投稿に失敗しました"
end
end
def destroy
@article = Article.find(params[:article_id])
@comment = @article.comments.find(params[:id])
@comment.destroy
redirect_to @article, notice: "コメントを削除しました"
end
private
def comment_params
params.expect(comment: [:body, :parent_id]) # Rails 8.0の書き方(→ [第13章](https://qiita.com/harapeco-mgn/items/15d2edb98bde321b3b10)で詳しく解説)
end
end
ネストの深さに注意
# ❌ ネストが深すぎる — URLが長くなりすぎて使いにくい
resources :users do
resources :articles do
resources :comments do
resources :likes # /users/1/articles/2/comments/3/likes/4 😱
end
end
end
# ✅ ネストは1段階まで — Railsの慣習
resources :articles do
resources :comments, only: [:create, :destroy] # 1段階のネスト
end
resources :likes, only: [:create, :destroy] # いいねはネストしない
一般的に、 ネストは1段階まで にするのがRailsの慣習です。深くなりすぎるとURLが長くなり、コントローラも複雑になります。
🎯 member と collection — 特別な窓口を追加する
7つの標準アクション以外に、追加のルートが必要な場合があります。KnowledgeNoteでは、ユーザーの「フォロー中一覧」「フォロワー一覧」がそれにあたります。
member — 特定の1件に対する追加アクション
resources :users, only: [:index, :show, :edit, :update, :destroy] do
member do
get :following # GET /users/:id/following
get :followers # GET /users/:id/followers
end
end
member は 特定のユーザー(:id指定) に対するアクションを追加します。「ユーザー3のフォロー一覧」のように、IDが必要です。
collection — コレクション全体に対する追加アクション
resources :articles do
collection do
get :search # GET /articles/search
end
end
collection は 記事全体 に対するアクションを追加します。特定のIDは不要です。「記事を検索する」のように、コレクション全体を対象にした操作に使います。
member と collection の違い
| member | collection | |
|---|---|---|
| URL | /users/:id/following |
/articles/search |
| :id | 必要(特定の1件) | 不要(全体が対象) |
| 使い方 | following_user_path(user) |
search_articles_path |
🔍 ルーティングの確認方法
定義したルートを確認するコマンドがあります。開発中によく使います。
# 全ルートを一覧表示
$ rails routes
# 特定のコントローラのルートだけ表示
$ rails routes -c articles
# grepで絞り込み
$ rails routes | grep article
# 出力例
Prefix Verb URI Pattern Controller#Action
articles GET /articles(.:format) articles#index
POST /articles(.:format) articles#create
new_article GET /articles/new(.:format) articles#new
edit_article GET /articles/:id/edit(.:format) articles#edit
article GET /articles/:id(.:format) articles#show
PATCH /articles/:id(.:format) articles#update
PUT /articles/:id(.:format) articles#update
DELETE /articles/:id(.:format) articles#destroy
Prefix の列が名前付きルートのヘルパー名(_path / _url をつけて使う)です。
🛠️ KnowledgeNoteでの具体例
KnowledgeNoteの routes.rb 全体を確認します。ここまで学んだ概念がすべて使われています。
# config/routes.rb
Rails.application.routes.draw do
# トップページ
root "static_pages#home"
# カスタムルート(名前付き)
get "/about", to: "static_pages#about"
get "/signup", to: "users#new"
post "/signup", to: "users#create"
get "/login", to: "sessions#new"
post "/login", to: "sessions#create"
delete "/logout", to: "sessions#destroy"
# ユーザー(member でフォロー一覧を追加)
resources :users, only: [:index, :show, :edit, :update, :destroy] do
member do
get :following, :followers
end
end
# 記事(ネストしたコメント付き)
resources :articles do
resources :comments, only: [:create, :destroy]
end
# フォロー・いいね(作成と削除のみ)
resources :follows, only: [:create, :destroy]
resources :likes, only: [:create, :destroy]
# タグ(名前で検索)
resources :tags, only: [:show], param: :name
# 通知(一覧のみ)
resources :notifications, only: [:index]
# メール認証・パスワード再設定
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
end
注目ポイントをいくつか取り上げます。
# ① カスタムURL — /signup は users#new より直感的
get "/signup", to: "users#new" # /users/new でもアクセスできるが、
# /signup の方がユーザーにわかりやすい
# ② param: :name — IDではなくタグ名でアクセス
resources :tags, only: [:show], param: :name
# → GET /tags/Ruby(IDではなく名前でアクセス)
# ③ only: で必要なルートだけ開ける
resources :likes, only: [:create, :destroy]
# → いいねは「つける」と「外す」だけ。一覧や編集は不要
💼 面接で聞かれたら?
Q:RESTful設計について説明してください。
「RESTfulとは、URLでリソース(対象)を表し、HTTPメソッドで操作を表す設計指針です。たとえば
/articlesというURLに対して、GETで取得、POSTで作成、PATCHで更新、DELETEで削除を行います。Railsではresourcesメソッドで、1つのリソースに対するCRUD操作のルートを7つ自動生成できます。」深掘りされたら:
- 「7つのアクションを全部言えますか?」→ index(一覧)、show(詳細)、new(作成フォーム)、create(作成処理)、edit(編集フォーム)、update(更新処理)、destroy(削除)。
- 「ネストしたリソースとは?」→ コメントのように、親リソース(記事)に従属する子リソースをURLで表現する仕組み。
/articles/:article_id/commentsのように、親のIDをURLに含める。ネストは1段階までが慣習。
🔗 もっと深く知りたい人へ(1次情報リンク)
- Rails ガイド:Rails のルーティング — resources, ネスト, member/collection の全パターンを網羅
- Rails API:ActionDispatch::Routing — ルーティングの全メソッド
- MDN Web Docs:HTTP リクエストメソッド — GET/POST/PATCH/DELETEの仕様
まとめ
- ✅
resources :articlesで7つのRESTfulルートが自動生成される - ✅ RESTfulとは「URLはリソース、HTTPメソッドは操作」を表す統一設計
- ✅
only:で必要なルートだけ開ける。不要な窓口は閉じておく - ✅ 名前付きルート(
_path/_url)でURLをニックネームで管理し、DRYを実現 - ✅ ネストしたリソースは1段階まで。
memberは個別、collectionは全体への追加アクション
📚 シリーズ目次:「今さら学ぶ」シリーズ — はじめに