Railsのroutingにおけるscope / namespace / module の違い

# はじめに

以前書いた、下記の続き。
https://qiita.com/ryosuketter/items/1d9b620fa2508cfda37b

今回は、Railsのroutingにおけるscope / namespace / module の違いについて書きます。

# 結論

結論をまとめると

| | URL | ファイル構成 |
|-----------|------------|------------|
| scope       | 指定のパスにしたい        | 変えたくない         |
| namespace     | 指定のパスにしたい      | 指定のパスにしたい       |
| module       | 変えたくない        | 指定のパスにしたい         |

以下、詳細を説明します。

# scope

以下の場合はscopeが望ましい

- URLは指定のパスにしたい
- ファイル構成変えたくない

```rb:config/routes.rb
Rails.application.routes.draw do
  scope :blog do
    resources :articles
  end
end
```

## scope / routing

<table>
  <thead>
    <tr>
      <th>Helper</th>
      <th>HTTP Verb</th>
      <th>Path</th>
      <th>Controller#Action</th>
    </tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="articles">
      articles<span class="helper">_path</span>
  </td>
  <td>
    GET
  </td>
  <td data-route-path="/blog/articles(.:format)">
    /blog/articles(.:format)
  </td>
  <td>
    <p>articles#index</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="">
  </td>
  <td>
    POST
  </td>
  <td data-route-path="/blog/articles(.:format)">
    /blog/articles(.:format)
  </td>
  <td>
    <p>articles#create</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="new_article">
      new_article<span class="helper">_path</span>
  </td>
  <td>
    GET
  </td>
  <td data-route-path="/blog/articles/new(.:format)">
    /blog/articles/new(.:format)
  </td>
  <td>
    <p>articles#new</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="edit_article">
      edit_article<span class="helper">_path</span>
  </td>
  <td>
    GET
  </td>
  <td data-route-path="/blog/articles/:id/edit(.:format)">
    /blog/articles/:id/edit(.:format)
  </td>
  <td>
    <p>articles#edit</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="article">
      article<span class="helper">_path</span>
  </td>
  <td>
    GET
  </td>
  <td data-route-path="/blog/articles/:id(.:format)">
    /blog/articles/:id(.:format)
  </td>
  <td>
    <p>articles#show</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="">
  </td>
  <td>
    PATCH
  </td>
  <td data-route-path="/blog/articles/:id(.:format)">
    /blog/articles/:id(.:format)
  </td>
  <td>
    <p>articles#update</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="">
  </td>
  <td>
    PUT
  </td>
  <td data-route-path="/blog/articles/:id(.:format)">
    /blog/articles/:id(.:format)
  </td>
  <td>
    <p>articles#update</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="">
  </td>
  <td>
    DELETE
  </td>
  <td data-route-path="/blog/articles/:id(.:format)">
    /blog/articles/:id(.:format)
  </td>
  <td>
    <p>articles#destroy</p>
  </td>
</tr>
  </tbody>
</table>

## scope / ファイル構成

<img width="295" alt="スクリーンショット 2019-03-17 22.50.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/14191/d22004ba-5a5f-2a70-d32a-c5854d7a485c.png">

## scope / controller

```rb:app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
  ...
end
```

そのままですね。

# namespace

以下の場合はnamespaceが望ましい

- URLは指定のパスにしたい
- ファイル構成も指定のパスにしたい

```rb:config/routes.rb
Rails.application.routes.draw do
  namespace :blog do
    resources :articles
  end
end
```

## namespace / routing

<table>
  <thead>
    <tr>
      <th>Helper</th>
      <th>HTTP Verb</th>
      <th>Path</th>
      <th>Controller#Action</th>
    </tr>
  </thead>
  <tbody>
<tr class="route_row" data-helper="path">
  <td data-route-name="blog_articles">
      blog_articles<span class="helper">_path</span>
  </td>
  <td>
    GET
  </td>
  <td data-route-path="/blog/articles(.:format)">
    /blog/articles(.:format)
  </td>
  <td>
    <p>blog/articles#index</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="">
  </td>
  <td>
    POST
  </td>
  <td data-route-path="/blog/articles(.:format)">
    /blog/articles(.:format)
  </td>
  <td>
    <p>blog/articles#create</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="new_blog_article">
      new_blog_article<span class="helper">_path</span>
  </td>
  <td>
    GET
  </td>
  <td data-route-path="/blog/articles/new(.:format)">
    /blog/articles/new(.:format)
  </td>
  <td>
    <p>blog/articles#new</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="edit_blog_article">
      edit_blog_article<span class="helper">_path</span>
  </td>
  <td>
    GET
  </td>
  <td data-route-path="/blog/articles/:id/edit(.:format)">
    /blog/articles/:id/edit(.:format)
  </td>
  <td>
    <p>blog/articles#edit</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="blog_article">
      blog_article<span class="helper">_path</span>
  </td>
  <td>
    GET
  </td>
  <td data-route-path="/blog/articles/:id(.:format)">
    /blog/articles/:id(.:format)
  </td>
  <td>
    <p>blog/articles#show</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="">
  </td>
  <td>
    PATCH
  </td>
  <td data-route-path="/blog/articles/:id(.:format)">
    /blog/articles/:id(.:format)
  </td>
  <td>
    <p>blog/articles#update</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="">
  </td>
  <td>
    PUT
  </td>
  <td data-route-path="/blog/articles/:id(.:format)">
    /blog/articles/:id(.:format)
  </td>
  <td>
    <p>blog/articles#update</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="">
  </td>
  <td>
    DELETE
  </td>
  <td data-route-path="/blog/articles/:id(.:format)">
    /blog/articles/:id(.:format)
  </td>
  <td>
    <p>blog/articles#destroy</p>
  </td>
</tr>
  </tbody>
</table>

## namespace / ファイル構成

<img width="272" alt="スクリーンショット 2019-03-17 22.29.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/14191/15e40373-2e1f-9af0-9ade-3e02b669d3b2.png">

## namespace / controller

```rb:app/controllers/blog/articles_controller.rb
class Blog::ArticlesController < ApplicationController
  ...
end
```

`Blog::`が接頭辞ぽく付きましたね。

# module

以下の場合はmoduleが望ましい

- URLは変えたくない
- ファイル構成だけ指定のパスにしたい


```rb:config/routes.rb
Rails.application.routes.draw do
  scope module: :blog do
    resources :articles
  end
end
```

## module / routing

<table id="route_table" class="route_table">
  <thead>
    <tr>
      <th>Helper</th>
      <th>HTTP Verb</th>
      <th>Path</th>
      <th>Controller#Action</th>
    </tr>
  </thead>
  <tbody>
<tr class="route_row" data-helper="path">
  <td data-route-name="articles">
      articles<span class="helper">_path</span>
  </td>
  <td>
    GET
  </td>
  <td data-route-path="/articles(.:format)">
    /articles(.:format)
  </td>
  <td>
    <p>blog/articles#index</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="">
  </td>
  <td>
    POST
  </td>
  <td data-route-path="/articles(.:format)">
    /articles(.:format)
  </td>
  <td>
    <p>blog/articles#create</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="new_article">
      new_article<span class="helper">_path</span>
  </td>
  <td>
    GET
  </td>
  <td data-route-path="/articles/new(.:format)">
    /articles/new(.:format)
  </td>
  <td>
    <p>blog/articles#new</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="edit_article">
      edit_article<span class="helper">_path</span>
  </td>
  <td>
    GET
  </td>
  <td data-route-path="/articles/:id/edit(.:format)">
    /articles/:id/edit(.:format)
  </td>
  <td>
    <p>blog/articles#edit</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="article">
      article<span class="helper">_path</span>
  </td>
  <td>
    GET
  </td>
  <td data-route-path="/articles/:id(.:format)">
    /articles/:id(.:format)
  </td>
  <td>
    <p>blog/articles#show</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="">
  </td>
  <td>
    PATCH
  </td>
  <td data-route-path="/articles/:id(.:format)">
    /articles/:id(.:format)
  </td>
  <td>
    <p>blog/articles#update</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="">
  </td>
  <td>
    PUT
  </td>
  <td data-route-path="/articles/:id(.:format)">
    /articles/:id(.:format)
  </td>
  <td>
    <p>blog/articles#update</p>
  </td>
</tr>
<tr class="route_row" data-helper="path">
  <td data-route-name="">
  </td>
  <td>
    DELETE
  </td>
  <td data-route-path="/articles/:id(.:format)">
    /articles/:id(.:format)
  </td>
  <td>
    <p>blog/articles#destroy</p>
  </td>
</tr>
  </tbody>
</table>

## module / ファイル構成

<img width="272" alt="スクリーンショット 2019-03-17 22.29.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/14191/15e40373-2e1f-9af0-9ade-3e02b669d3b2.png">

## module / controller

```rb:app/controllers/blog/articles_controller.rb
class Blog::ArticlesController < ApplicationController
  ...
end
```

こちらも、`Blog::`が接頭辞ぽく付きましたね。

以上です！

# 参考

- https://qiita.com/takehanKosuke/items/79a66751fe95010ea5ee
- https://qiita.com/ko2ic/items/be96e450a33d631e0059