【Ruby on Rails】RESTfulなルーティング設計(resources)の考え方

Ruby

こんにちは、かつコーチです。

routes.rbresources :posts と1行書くだけで、たくさんのルートが自動生成される。

初めて見たとき「便利だけど、結局何が作られているのかわからない」と感じませんでしたか。

私も最初は rails routes の出力を見ても、どのアクションがどのURLに対応するのか整理できませんでした。

この記事では、RESTful(リソースをURLとHTTPメソッドの組み合わせで統一的に表現する設計思想です)という考え方と、resources が自動生成する7つのルートを、実際のコードとセットで解説します。

読み終えるころには、なぜRailsが resources を標準にしているのか腹落ちしているはずです。

RESTfulとは?

リソース指向の考え方

REST(Representational State Transfer)とは、Webサービスを「リソース」(データのまとまり、例えば「投稿」や「ユーザー」)の集合として捉え、それに対する操作をHTTPメソッドで表現する設計思想です。

例えば「投稿」というリソースに対する操作は、次のように整理できます。

操作HTTPメソッド意味
一覧を見るGET投稿一覧を取得する
詳細を見るGET特定の投稿を取得する
新規作成するPOST投稿を新しく作る
更新するPATCH/PUT投稿を書き換える
削除するDELETE投稿を消す

URLは「何のリソースか」だけを表し、「何をするか」はHTTPメソッドが表す。

これがRESTfulな設計の基本です。

なぜRailsはresourcesを推奨するのか

RESTfulな設計にすると、URLの命名に迷わなくなります。

「投稿を編集する画面のURLは /posts/edit_form かな、それとも /posts/1/edit かな」と毎回考える必要がなくなるからです。

Railsは「設定より規約」という思想のフレームワークなので、この規約に沿ったURL設計を resources 1行で実現できるようにしています。

resources :xxxで自動生成される7つのルート

実際に書いてみる

まずは config/routes.rb に以下を追記します。

# config/routes.rb
Rails.application.routes.draw do
  resources :posts
end

この1行だけで、以下の7つのルートが自動生成されます。

$ bin/rails routes -g posts

    Prefix Verb   URI Pattern               Controller#Action
     posts GET    /posts                    posts#index
           POST   /posts                    posts#create
  new_post GET    /posts/new                posts#new
 edit_post GET    /posts/:id/edit           posts#edit
      post GET    /posts/:id                posts#show
           PATCH  /posts/:id                posts#update
           PUT    /posts/:id                posts#update
           DELETE /posts/:id                posts#destroy

7つのアクションと役割

アクション役割対応するURL例
index一覧表示GET /posts
show詳細表示GET /posts/1
new新規作成フォーム表示GET /posts/new
create新規作成の実行POST /posts
edit編集フォーム表示GET /posts/1/edit
update更新の実行PATCH /posts/1
destroy削除の実行DELETE /posts/1

コントローラ側は、この規約に沿ってアクションを定義するだけです。

# app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def index
    @posts = Post.all
  end

  def show
    @post = Post.find(params[:id])
  end

  def new
    @post = Post.new
  end

  def create
    @post = Post.new(post_params)
    if @post.save
      redirect_to @post, notice: "投稿を作成しました。"
    else
      render :new, status: :unprocessable_entity
    end
  end

  def edit
    @post = Post.find(params[:id])
  end

  def update
    @post = Post.find(params[:id])
    if @post.update(post_params)
      redirect_to @post, notice: "投稿を更新しました。"
    else
      render :edit, status: :unprocessable_entity
    end
  end

  def destroy
    @post = Post.find(params[:id])
    @post.destroy
    redirect_to posts_path, notice: "投稿を削除しました。", status: :see_other
  end

  private

  def post_params
    params.require(:post).permit(:title, :body)
  end
end

パスヘルパーを使う

rails routes の出力にある Prefix 列(postsnew_post など)は、パスヘルパー(URLを直接書かずに済むメソッドです)の元になります。

<%# app/views/posts/index.html.erb %>
<%= link_to "新規投稿", new_post_path %>

<% @posts.each do |post| %>
  <%= link_to post.title, post_path(post) %>
<% end %>

URLを文字列で直接書いてしまうと、後でルーティングを変更したときに全ファイルを修正する必要が出てきます。

パスヘルパーを使えば、その心配がありません。

よくあるつまずきポイント・エラー対処

全アクションを自動生成してしまい、使わないルートが残る

❌ Before:使わないアクションまで含めて全公開してしまう

# config/routes.rb
Rails.application.routes.draw do
  resources :posts
end

管理者しか使わない destroy まで誰でも呼び出せる状態になっていないか、必ず確認しましょう。

実際に私は、削除機能をまだ実装していない段階で resources :posts とだけ書いてしまい、フォームもコントローラもない destroy のルートだけが存在するという中途半端な状態にしてしまったことがあります。

エラーにはなりませんが、rails routes で見たときに「これは本当に必要なアクションか」を毎回意識するようにしています。

✅ After:必要なアクションだけをonly/exceptで絞り込む

# config/routes.rb
Rails.application.routes.draw do
  resources :posts, only: [:index, :show, :new, :create]
end

管理画面など、更新・削除も必要な場合は逆に except で絞り込むと読みやすくなります。

# config/routes.rb
Rails.application.routes.draw do
  namespace :admin do
    resources :posts, except: [:new, :create]
  end
end

必要なアクションだけを明示することで、意図しないルートの公開を防げますし、rails routes の出力も見やすくなります。

まとめ

この記事のポイント

  • RESTfulとは、URLとHTTPメソッドでリソースへの操作を統一的に表現する設計思想
  • resources :posts で index/show/new/create/edit/update/destroyの7ルートが自動生成される
  • パスヘルパー(posts_path など)を使うとURLの変更に強いコードになる
  • only / except で不要なルートを絞り込み、意図しない公開を防ぐ

次に読むべき記事

  • ルーティングの基本:config/routes.rbの書き方
  • コントローラの基本:アクションとストロングパラメータ

タグ: Ruby on Rails, 中級者向け, フレームワーク基礎

タイトルとURLをコピーしました