0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

rails ルーティング

Posted at

はじめに

今回は公式ドキュメントをもとにコメントなどを入れながら、railsルーティングをまとめてみたいと思います。

基本的な書き方

config/routes.rb はRailsアプリケーションで使用されるルーティングに関する情報を含むファイルです。
このファイルにルートを定義することで、アプリケーションのURLとコントローラーのアクションを関連付けることができます。

基本的なルーティングの書き方は以下のようになります。

get '/users/:id', to: 'users#show', as: 'user'
get 'profile', action: :show, controller: 'users'

resourceとresources

先ほど基本的なルーティングの書き方を示しましたが、実はそこまで使う機会は多くありません。
どちらかといえばこれから紹介する方法で書くことが多いので、ぜひそちらの書き方を押さえましょう。

resource :user
HTTP verb パス コントローラ#アクション 目的
GET /users/new users#new ユーザー作成用のHTMLフォームを返す
POST /users users#create ユーザーを作成する
GET /users/:id users#show 1つしかないuserリソースを表示する
GET /users/:id/edit users#edit ユーザー編集用のHTMLフォームを返す
PATCH/PUT /users/:id users#update 1つしかないuserリソースを更新する
DELETE /users/:id users#destroy userリソースを削除する
resrouces :users
HTTP verb パス コントローラ#アクション 目的
GET /users users#index すべてのユーザーの一覧を表示
GET /users/new users#new ユーザーを1つ作成するためのHTMLフォームを返す
POST /users users#create ユーザーを1つ作成する
GET /users/:id users#show 特定のユーザーを表示する
GET /users/:id/edit users#edit ユーザー編集用のHTMLフォームを1つ返す
PATCH/PUT /users/:id users#update 特定のユーザーを更新する
DELETE /users/:id users#destroy 特定のユーザーを削除する

これらの大きな違いは2つあります。
1、resourceはindexアクションを作成しない
2、resourceは:idを作成しない

以上から、以下のような使い分けになります。

複数のリソース=>resources
単一のリソース=>resource

resourceは例えばログインしている場合などがそうですね。
わざわざidを取得する必要がないので、その場合はresourceとなります。

namespace

namespaceメソッドは、Railsのルーティングシステムで、特定のコントローラーやビューに名前空間を設定するために使用されます。名前空間は、関連するコントローラー、ビュー、およびヘルパーをグループ化することができます。

要は、プレフィックスをつけられるということです。

admin画面などが多い気がしますが、例えば以下のように書くと
resource :usersで作成したroutesの頭にadminがつきます。

  namespace :admin do
   resources :users
  end
HTTP verb パス コントローラ#アクション 名前付きルーティングヘルパー
GET /admint/users admin/users#index admin_users_path
GET /admin/users/new adming/users#new new_admin_user
POST /admin/users admin/users#create admin_users_path
GET /admin/users/:id admin/users#show admin_user_path(:id)
GET /admin/users/:id/edit admin/users#edit edit_admin_user_path(:id)
PATCH/PUT /admin/users/:id admin/users#update admin_user_path(:id)
DELETE /admin/users/:id admin/users#destroy admin_user_path(:id)

公式ドキュメントは以下のように補足が書かれています。

例外的に、(/adminが前についていない) /articlesをAdmin::ArticlesControllerにルーティングしたい場合は、以下のようにすることもできます。

scope module: 'admin' do
  resources :articles, :comments
end

以下のようにブロックを使わない記述も可能です。

resources :articles, module: 'admin'

逆に、/admin/articlesを (Admin::なしの) ArticlesControllerにルーティングしたい場合は、以下のようにscopeブロックでパスを指定できます。

scope '/admin' do
  resources :articles, :comments
end

以下のように単数形ルーティングでもできます。

resources :articles, path: '/admin/articles'

ルーティングのネスト

ルーティングはこれまでのような書き方だと対応できない場合が出てきます。
例えば、「書籍にコメントをする」みたいな機能がある場合、様々な書籍に様々なコメントがあるわけです。

「ある本のあるコメントを表示したいな」と考えた時には、これまでのルーティングでは対応できません。そんな時にルーティングをネストさせる必要があります。

resources :books do
  resources :comments
end

このように書いた場合、以下のようにルーティングが生成されます。

Prefix         Verb    URI Pattern                            Controller#Action
book_comments GET     /books/:book_id/comments(.:format)     comments#index
              POST    /books/:book_id/comments(.:format)     comments#create
new_book_comment GET /books/:book_id/comments/new(.:format) comments#new
edit_book_comment GET /books/:book_id/comments/:id/edit(.:format) comments#edit
book_comment GET     /books/:book_id/comments/:id(.:format) comments#show
              PATCH   /books/:book_id/comments/:id(.:format) comments#update
              PUT     /books/:book_id/comments/:id(.:format) comments#update
              DELETE  /books/:book_id/comments/:id(.:format) comments#destroy

このように生成すると、例えば書籍とコメントのどちらもidがついているので、
それぞれのidを指定することで、特定の書籍に対する特定のコメントを表示できるわけですね。

/books/:book_id/comments/:id

ただし、注意点としてネストさせると複雑になるため、多くても1回が良いです。
それ以上する場合は、index/new/createのようなidを持たないもの(コレクション)のアクションだけを親のスコープの下で生成するという手法があります。

resources :books do
  resources :comments, only: [:index, :new, :create]
end
resources :comments, only: [:show, :edit, :update, :destroy]

これは、shallowオプションを書くことで浅いネストを実現できます。(結果は上と同じです。)

resources :articles do
  resources :comments, shallow: true
end

また、shallowをブロックで書くこともできます。

shallow do
  resources :books do
    resources :comments
    resources :quotes
    resources :drafts
  end
end

どのような出力をしたいのかに応じて使い分けていきましょう。

ルーティングのconcern機能

concernを使うことで、他のリソースやルーティング内で使い回せる共通のルーティングを宣言できます。
これは、まあ使っても使わなくてもいい気がします。こんなものもあるんだなという認識で良いと思います。

concern :commentable do
  resources :comments
end

concern :image_attachable do
  resources :images, only: :index
end

concernを利用すると、同じようなルーティングを繰り返し記述せずに済み、
複数のルーティング間で同じ振る舞いを共有できます。

resources :messages, concerns: :commentable

resources :articles, concerns: [:commentable, :image_attachable]

上のコードは以下と同等です。(個人的にはこっちの方がわかりやすい、、、)

resources :messages do
  resources :comments
end

resources :articles do
  resources :comments
  resources :images, only: :index
end

複数形のconcerns呼び出しはルーティング内のどの場所にでも配置できます。scopeやnamespaceブロックでは以下のように利用できます。

namespace :articles do
  concerns :commentable
end

memberとcollection

他にもルーティングをさらにカスタマイズしたい場合にmemberやcollectionがあります。
どちらも似たような使い方ですが、idを付与するかどうかに大きな違いがあります。

結論から伝えると以下の通りです。

member=>idを付与する
collection=>idを付与しない

まあ名前の通り、memberは1人、2人のようなイメージなのでidがつくという感じですかね。

member

resources :users do
  member do
    get 'hoge'
  end
end

上記のように member を使用すると以下のようにルーティングが設定されます。
/usersにidとhogeが乗っている(on)感じですね。

/users/:id/hoge

アクションが1つだけの場合は、以下のように書きます。

resources :users do
  get 'hoge', on: :member
end

collection

resources :users do
  collection do
    get 'hoge'
  end
end

上記のようにcollection を使用すると以下のようなルーティングが設定されます。
/usersにhogeが乗っている(on)感じですね。

/users/hoge

こちらもアクションが1つだけの場合は、以下のように書きます。

resources :users do
  get 'hoge', on: :collection
end

7つのルーティングやネストだと対応できないなとなった時に使用を検討してみましょう。

名前付きルーティング :as

:asオプションを使うと、任意のルーティングに名前を指定できます。
名前付きルーティングを使用すると、以下のようなメリットがあります。

  • コードの可読性が向上する
  • URLの変更にも柔軟に対応できる

例えば、以下のようなルーティングがあるとします。

get '/books/:id', to: 'books#show'

このルーティングは、/books/:id というURLにGETリクエストが送信された場合、BooksControllerの showアクションが呼び出されます。

名前付きルーティングを使用すると、以下のように書くことができます。

get '/books/:id', to: 'books#show', as: :book

このルーティングでは、:book という名前が付けられています。

これにより、ルートを参照するための短いエイリアスが作成されます。
例えば、ビューから book_path(@book) というメソッドを呼び出すことで、/books/:id というURLにアクセスできます。

ルートが複雑である場合や、複数のビューやコントローラーで同じルートを参照する場合は、名前付きルートを積極的に使用することをおすすめします。

既存のルーティングを表示する

--expanded

--expandedオプションを使うと以下のように表示できるらしい。めっちゃ見やすい...
でもrailsのバージョンによっては使用できないみたいです...(少なくともRails 5.2.3では使用できませんでした。)

--[ Route 1 ]----------------------------------------------------
Prefix            | users
Verb              | GET
URI               | /users(.:format)
Controller#Action | users#index
--[ Route 2 ]----------------------------------------------------
Prefix            |
Verb              | POST
URI               | /users(.:format)
Controller#Action | users#create

-g

これはgrepオプションですね。多くの人が使っていると思います。
以下を実行するとURLヘルパー名、HTTP verb、URLパスのいずれかに部分マッチするルーティングが出力されます。

rails routes -g users

以下のようにもかけますが、-gの方がいいですね。

rails routes | grep users

-c

特定のコントローラに対応するルーティングだけを表示したい場合は、-cオプションを使います。

-gオプションだと、URLヘルパー名、HTTP verb、URLパスのいずれかに部分マッチするルーティングを出力するので、controllerに含まれているルーティングだけ知りたい場合は-cをつけると良いです。

まとめ

以上がrailsルーティングのまとめになります。
個人的にあんまり使わないなという部分は飛ばしたりしているので、より詳しく知りたい方は公式ドキュメントを参照してみると良いと思います。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?