Railsでのルーティングを解説

# はじめに
ルーティングって市販の教材とかだと基本的なことしか載っていなかったり「するけど、
実務だと市販教材には載っていない使い方とかよくあったりします。

そんなルーティングの使い方を紹介していきます。

# rails routesコマンドを使ってルーティングの確認
***アプリケーション内で定義されている全てのルートが一覧表示***されます。
これには、```HTTPメソッド、URLパス、コントローラーとアクション```、そしてそれぞれの***ルートに対するヘルパーメソッドなどのがわかる***ので、***アプリケーション全体のURL構造やルーティング設定を確認***できます。

例えばgrep機能も使えたりします。
```
rails routes |grep api/v1
```
これは***ルーティングでapi/v1という文字列を含む行だけを抽出して表示するためのコマンド***です。
```
api_v1_articles GET    /api/v1/articles(.:format)                                                               api/v1/articles#index
                                      POST   /api/v1/articles(.:format)                                                               api/v1/articles#create
                       api_v1_article GET    /api/v1/articles/:id(.:format)                                                           api/v1/articles#show
                                      PATCH  /api/v1/articles/:id(.:format)                                                           api/v1/articles#update
                                      PUT    /api/v1/articles/:id(.:format)                                                           api/v1/articles#update
                                      DELETE /api/v1/articles/:id(.:format)                                                           api/v1/articles#destroy
```
みたいな感じで表示されたりします。

# root
最初にユーザーがアプリケーションにアクセスしたときに表示されるページを指定できます。
ユーザーが最初にアプリケーションにアクセスしたとき、WelcomeControllerのindexアクションを表示する
という意味で、WelcomeControllerは例えば「ようこそ！」と書かれたページを表示する役割を果たしたりします。

```routes.rb
Rails.application.routes.draw do
  root to: 'welcome#index'
  #中略
end
```

# resourcesについて
Railsにおいて***RESTfulなルーティングを簡単に設定するのに役立ち***ます。

アプリケーションには様々なデータや情報があります。
例えば、X(旧Twitter)なら投稿、ユーザー、コメントなどが考えられ、
これらのデータを取り扱うときに、それぞれのデータに対して行える操作（表示、作成、更新、削除など）があります。

Railsのresourcesを使うと、これらのデータに対してRESTfulなアクションを簡単に作れます。
例えば、投稿に関するresourcesを設定すると、投稿一覧を表示するページ、新しい投稿を作成するページ、特定の投稿を表示するページ(実際はないですが)などが自動的に作られます。

```routes.rb
Rails.application.routes.draw do
  resources :posts
end
```
|URL|説明|
|--|--|
|GET /posts:|投稿一覧を表示するページ|
|GET /posts/new:|新しい投稿を作成するページ|
|GET /posts/:id|特定の投稿を表示するページ（:idは記事の識別子）|
|POST /posts:|新しい記事を作成するアクション|
|PATCH /posts/:id|特定の記事を更新するアクション|
|DELETE /posts/:id|特定の記事を削除するアクション|
 
簡単に言えば、resourcesはアプリケーションでは、さまざまなデータに対して
標準的なアクションを定義する手間を省いてくれる便利な機能です。
### only
他にもこんな使い方をしたことがあります。
```rb
 namespace :users do
    resources :posts, only: [:index]
  end
```
namespaceはこの後話します。onlyを使ったことがあります。

:postsはリソースの名前で、PostsControllerに対応することが期待され、
```only: [:index]```は、***このリソースに対してどのアクションを許可するかを指定***します。
indexアクションのみを有効にし、ユーザーが投稿の一覧を表示するためのものです。
結果として、GET /users/posts に対しては、PostsControllerのindexアクションが呼び出されます。

https://qiita.com/Hashimoto-Noriaki/items/441003dd2ec358a331b5

# コントローラー内のアクションで使うルーティング

```routes.rb
Rails.application.routes.draw do
  get  "static_pages/home"
  get  "static_pages/help"
  root "application#hello"

end
```
> 引用　https://railstutorial.jp/chapters/static_pages?version=7.0#aside-undoing_things

```get "static_pages/home"```とありますが、
このルールは、***/static_pages/home***という***URLに対するリクエスト***を、
***StaticPagesコントローラのhomeアクションと結びつけ***ています。
今回はgetと書かれているので、GETリクエストを受け取ったときに
対応するアクションを結びつけています。

チュートリアルだと
```https://中略/static_pages/home```のURLで表示されます。

⚫︎補足
GETとPOSTの説明はこの動画の解説が個人的にわかりやすかったです。
Laravelとなっていますが、Railsと似ているので問題ないかと思います。

https://www.youtube.com/watch?v=I-enAc-JLpw&t=1508s

# namespace
最初から下の様にバージョンで名前空間を作成しておくことで今後のAPIのバージョン管理が簡単になります。
***namespaceは、指定した名前空間にルーティングをまとめるためのもの***で、
この場合、***:usersという名前空間が指定***されています
名前空間を使用することで、同じ名前のコントローラーが別の名前空間内で存在しても競合することなく使えるようにします。

```routes.rb
Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :articles
      # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
    end
  end
end
```

# scope
***特定のURLに共通の言葉やディレクトリを追加***できます。
例えば/adminというURLにアクセスすると、それより後のURLは/adminになります。
これは管理者向けのページにアクセスするときに使います。
```routes.rb
scope '/admin' do
  resources :users
end
```

```module```の使い方も説明しておきます。
それぞれ***異なる機能を組み合わせてルーティングを整理し、モジュール化***するためのものです。
特定のページや機能がどのグループ（モジュール）に属するかを指定でき、
大きなプロジェクトでコードを整理するのに使います。

例えば、/admin/productsといったURLは、商品情報に関する管理者用のページにアクセスする場合に使います。
```routes.rb
scope '/admin', module: 'admin' do
  resources :products
end
```
コントローラーが所属するモジュールを指定でき、
***/admin/productsにアクセス***すると、***Admin::ProductsControllerが呼び出され***ます。


# collection
特定のリソース全体に関連するアクションを指定するために使います。
例えばプログラミングスクールのウェブアプリがあるとするとユーザー(生徒)がたくさんいて、
それぞれが日報、質問、プルリク、レビューなどの情報を持っているとします。
これらの情報は特定のユーザーに紐づいているのではなく、全てのユーザーに関連しています。

***collectionを使って、ユーザー全体に関連するアクションを指定***できます。
以下の例では、ユーザー全体の日報、プルリクエスト、質問、レビュー、コメントにアクセスするためのURLを定義します。

```routes.rb
resources :users, param: :student_id,only: [:index, :show]
    collection do
      resources :daily_reports, only: [:index]
      resources :pull_requests, only: [:index]
      resources :questions, only: [:index]
      resources :review, only: [:index]
      resources :comment, only: [:index]
    end
  end
```
UsersControllerに対して基本的なアクション（一覧と詳細）と、
ユーザー全体に関連するアクション（日報、プルリクエスト、質問、レビュー、コメントの一覧）を定義しています。

|REST|
|--|
|GET /users:ユーザー一覧を表示するページ（indexアクション）|
|GET /users/:student_id: 特定のユーザーの詳細を表示するページ（showアクション）|
|GET /users/daily_reports: 全てのユーザーの日報一覧を表示するページ|
|GET /users/pull_request: 全てのユーザーのプルリクエスト一覧を表示するページ|
|GET /users/questions: 全てのユーザーの質問一覧を表示するページ|
|GET /users/review: 全てのユーザーのレビュー一覧を表示するページ|
|GET /users/comment: 全てのユーザーのコメント一覧を表示するページ|

# 実務でこんな使い方をした
実際に実務でこんな使い方もしたというのもお伝えします。

```routes.rb
Rails.application.routes.draw do
  root to: 'Welcome#home'

  namespace :api do
    namespace :v1 do
      draw :student
      draw :issue
      draw :web
    end
  end
end
```
ここでdrawを使って別のroutesディレクトリの中のweb.rbにnamespaceを追加しました。
URLは以下のようにしました。
```
http://localhost:3000/api/v1/web/users/posts
```
上のコードでdraw :webを消したらエラーが出てしまいました。上のroute.rbで定義して
routesファイルの中にweb.rbを作ったりしました。studentやissueも同じ感じです。
```routes/web.rb
namespace :web do
  #中略

  namespace :users do
   #中略
  end

  resources :users, #中略
   #中略
    end
  end
end
```


# 資料
ChatGPT参照。

https://techtechmedia.com/namespace-scope-module-routing/

https://qiita.com/senou/items/f1491e53450cb347606b

https://railstutorial.jp/chapters/static_pages?version=7.0#aside-undoing_things