【Ruby on Rails】ルーティング scope と namespace の違い

概要

RailsAPI を作成するときに、URL 設計を気にすると思います。

例えは、ユーザ情報を操作する users API のエンドポイントを下記のようなパスで作成したいとします。

http://$(DNS)/api/v1/users

この場合、routes.rb をどう書くのか調べたところルーティングのメソッドに namespace と scope と言うものがありました。

この 2 つの使い方を簡単にまとめました。

namespace の使い方

namespace を使うときは、Controller に URL のパス同様に /api/v1/ のディレクトリを作成する必要があります。

$ tree app/controllers/
app/controllers/
├── api
│   └── v1
│       └── users_controller.rb
├── application_controller.rb
└── concerns

app/controllers/api/v1/users_controller.rb の中身は、module を使って URL のパス同様の構成にします。

$ cat app/controllers/api/v1/users_controller.rb
module Api
  module V1
    class UsersController < ApplicationController
      def index
       render json: { status: 200, message: 'Success' }
      end
    end
  end
end

routes.rb は namespace を利用すると、このように記載できます。

$ cat config/routes.rb
Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :users, only: :index
    end
  end
end

ルーティングを確認します。

ひとまず、作成したい API のエンドポイントが用意できました。

$ rake routes
      Prefix Verb URI Pattern             Controller#Action
api_v1_users GET  /api/v1/users(.:format) api/v1/users#index

最後にエンドポイントにアクセスできるか確認してみます。

$ curl 'http://localhost/api/v1/users'
{"status":200,"message":"Success"}

出来ました!レスポンスに想定通りの結果が返ってきました!

scope の使い方

scope を使うときには、Controller にわざわざディレクトリを作成する必要はありません。そのままで大丈夫です。

$ tree app/controllers/
app/controllers/
├── application_controller.rb
├── concerns
└── users_controller.rb

app/controllers/users_controller.rb の中身もそのままで大丈夫です。

$ cat users_controller.rb
class UsersController < ApplicationController
  def index
    render json: { status: 200, message: 'Success' }
  end
end

routes.rb は scope を利用すると、このように記載できます。

$ cat config/routes.rb
Rails.application.routes.draw do
  scope :api do
    scope :v1 do
      resources :users, only: :index
    end
  end
end

ルーティングを確認します。

ひとまず、作成したい API のエンドポイントが用意できました。

$ rake routes
Prefix Verb URI Pattern             Controller#Action
 users GET  /api/v1/users(.:format) users#index

最後に、エンドポイントにアクセスできるか確認してみます。

$ curl 'http://localhost/api/v1/users'
{"status":200,"message":"Success"}

こちらの方法でも、想定通りの結果を受けることが出来ました!

まとめ

namespace と scope で URL を設計する方法をまとめました。

routes.rb の記載方法はどちらも同じです。

大きく異なるのは namespace を利用するときは、Controller 内に実際の URL パスと同様のディレクトリ構成を作る必要があるという点です。

namespace と scope どちらを使って URL 設計すれば良いかは、アプリケーションによると思います。

例えば、Web サーバの機能の一部に API の機能が混じっているアプリケーションの場合、Contoroller 内に API 用のディレクトリを作成して、namespace を使った URL 設計を行うのが綺麗な気がします。

API 機能しかないアプリケーションであれば、コントローラー内にわざわざディレクトリを作成せずに、scope を使ってを URL 設計を使うのが綺麗な気がします。