ナスカブログ

未来の自分へのドキュメント

Rails ルーティング Tips

  • resources
  • resource
  • collection
  • member
  • namespace

ルーティングファイルの配置場所 config/routes.rb

Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  ## 以下に記述していく
end

resources

いくつかの書き方が存在する

## 1. 基本のアクション(index, new, create, show, edit, update, destroy)のルーティングが生成される
resources :posts

## 2. index, new, create, showのルーティングが生成される。
resources :posts, only: %i[index new create show]

## 3. destroy以外のアクションが生成される。
resources :posts, except: %i[destroy]

実務では2の書き方をよく見る。 必要なルーティングのみ生成する。

resourcesとresourceの違い

まず、生成されるルーティングの違いについてみていく

Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  resources :posts
  resource :post
end
  • 生成されるルーティングを確認する方法
    • ターミナルで rails routesコマンドを実行
% rails routes
      Prefix Verb   URI Pattern                  Controller#Action
    ########  resources :posts で生成されたルーティング ############
         posts GET    /posts(.:format)              posts#index
               POST   /posts(.:format)              posts#create
      new_post GET    /posts/new(.:format)          posts#new
     edit_post GET    /posts/:id/edit(.:format)     posts#edit
          post GET    /posts/:id(.:format)          posts#show
               PATCH  /posts/:id(.:format)          posts#update
               PUT    /posts/:id(.:format)          posts#update
               DELETE /posts/:id(.:format)          posts#destroy
    ########  resource :post で生成されたルーティング ############
               GET    /post/new(.:format)           posts#new
               GET    /post/edit(.:format)          posts#edit
               GET    /post(.:format)               posts#show
               PATCH  /post(.:format)               posts#update
               PUT    /post(.:format)               posts#update
               DELETE /post(.:format)               posts#destroy
               POST   /post(.:format)               posts#create

違いをいくつかまとめる

  • resources :posts
    • :idが存在する
  • resource :post
    • URI Patternの始めが/postで始まる
    • Controller#Actionにposts#indexがない

両者を使い分ける方法としては
特定のレコードを取得する際にidが必要かどうかで判断するといい

少し具体例を出して説明する

例えば ユーザーの基本的な情報(名前、メールアドレス)を保存するUserモデルが存在し
さらに詳しい情報(身長、体重、生年月日)を保存するProfileモデルが存在したとする

  • UserとProfileはhas_oneの関係になる(1対1)
  • Profileモデルは必ずUserのidに紐づく(Profileモデルがuser_idを持つ)

ある特定のユーザーのデータを取得する際はidが必要(idがないとレコードを特定できない)
しかしProfileのレコードは必ずユーザーに紐づくので特定のユーザーの情報さえ取得できればそれに紐づくProfileのレコードは特定できる
したがってProfileは特定のレコードを取得する際にidは不要

生成するルーティングとしてはUserはresources, Profileはresourceになる

Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  resources :users do
    resource :profile, only: %i[show edit update]
  end
end
% rails routes
                  Prefix Verb   URI Pattern          Controller#Action
 new_user_profile GET    /users/:user_id/profile/new(.:format)   profiles#new
edit_user_profile GET    /users/:user_id/profile/edit(.:format)  profiles#edit
     user_profile GET    /users/:user_id/profile(.:format)       profiles#show
                  PATCH  /users/:user_id/profile(.:format)       profiles#update
                  PUT    /users/:user_id/profile(.:format)       profiles#update
                  POST   /users/:user_id/profile(.:format)       profiles#create
            users GET    /users(.:format)                        users#index
                  POST   /users(.:format)                        users#create
         new_user GET    /users/new(.:format)                    users#new
        edit_user GET    /users/:id/edit(.:format)               users#edit
             user GET    /users/:id(.:format)                    users#show
                  PATCH  /users/:id(.:format)                    users#update
                  PUT    /users/:id(.:format)                    users#update
                  DELETE /users/:id(.:format)                    users#destroy

profileのdestroyアクションはおそらくUserのdestroyメソッドを使用した時にprofileも同時に削除されるような実装をすると思うので外した。

collection

## 1.一つだけルーティングを生成する場合
get 'search', on: :collection

## 2.複数ルーティングを生成する場合
collection do
  get 'search'
  get 'download_file'
  :
end

さっきのユーザーのルーティングに新たに検索機能(searchアクション)を追加する場合

resources :users do
  resource :profile, only: %i[new create show edit update]
  collection do
    get 'search'
  end
end

生成されるルーティング

% rails routes
      Prefix Verb   URI Pattern               Controller#Action
## 省略
search_users GET    /users/search(.:format)   users#search
## 省略

collectionとmemberの違い

生成されるルーティングの違い

resources :users do
  resource :profile, only: %i[new create show edit update]
  get 'search', on: :collection
  get 'search', on: :member
end
% rails routes
      Prefix Verb   URI Pattern                    Controller#Action
## 省略
search_users GET    /users/search(.:format)        users#search
 search_user GET    /users/:id/search(.:format)    users#search
## 省略
  • memberの方はidがつく