iT邦幫忙

2022 iThome 鐵人賽

DAY 17
0
Modern Web

一探紅寶石的神秘面紗 - Ruby 及 Rails入門介紹 系列系列 第 17

Day 17 - 進入Rails世界必須懂:Routes (下)

  • 分享至 

  • xImage
  •  

延續前面基本的路徑設計,這篇會提到比較多種巢狀設計的方式。

巢狀設計方式

resources 方法裡面其實還可以在包 resources,在後面會提到 model 之間關連性,例如一個 User 可能會有很多 Articles,Route 可能會這樣寫:

Rails.application.routes.draw do
  resources :users do
    resource :articles
  end
end

終端機輸入 $ rails routes -c articles 查詢路徑可以看到如下

            Prefix Verb   URI Pattern                             Controller#Action
 new_user_articles GET    /users/:user_id/articles/new(.:format)  articles#new
edit_user_articles GET    /users/:user_id/articles/edit(.:format) articles#edit
     user_articles GET    /users/:user_id/articles(.:format)      articles#show
                   PATCH  /users/:user_id/articles(.:format)      articles#update
                   PUT    /users/:user_id/articles(.:format)      articles#update
                   DELETE /users/:user_id/articles(.:format)      articles#destroy
                   POST   /users/:user_id/articles(.:format)      articles#create

路徑內就包含特定"使用者"與"文章"之間的關係,像是:
/users/1/articles/new => 使用者 1 號的空間新增文章
/users/2/articles/3/edit => 使用者 2 號的空間對 3 號文章做修改

你也可以繼續往下包resources,但是建議是 2 層最多,在下去可能變得太冗長,像是這樣:
/users/Sean/articles/6/comments/3

Shallow

會使用到這個簡化方法主要是在一些 action 不需要用到上一層資源相關的 id 我們可以透過 shallow 去設計
像是下面這樣的狀況,要呈現留言板在文章內,index, new, create 這 3 種需要知道是針對哪篇文章進行留言或顯示所有留言,所以會要保留article id,但是在 show, edit, update, destroy,不需要知道 article id,只要針對 comment id 就可以進行相關動作。

resources :articles do
  resources :comments, only: [:index, :new, :create] # 這3種 action 需要標出 article id
end
resources :comments, only: [:show, :edit, :update, :destroy] # 這些不需要標出 article id
             Prefix Verb   URI Pattern                                  Controller#Action
   article_comments GET    /articles/:article_id/comments(.:format)     comments#index
                    POST   /articles/:article_id/comments(.:format)     comments#create
new_article_comment GET    /articles/:article_id/comments/new(.:format) comments#new
       edit_comment GET    /comments/:id/edit(.:format)                 comments#edit
            comment GET    /comments/:id(.:format)                      comments#show
                    PATCH  /comments/:id(.:format)                      comments#update
                    PUT    /comments/:id(.:format)                      comments#update
                    DELETE /comments/:id(.:format)                      comments#destroy

上面的寫法可以利用 shallow 來簡化如下,產生出來的路徑都是相同。

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

collection 與 member

如果預設的路徑不夠使用,且層層包裹之中,又希望設計要或不要帶有前面一層的 id 可以這樣表示
collection => 沒有 id
member => 有 id

Rails.application.routes.draw do
  resources :friends do
    collection do
      # /friends/confirmed
      get :confirmed 
    end
    member do
      # /friends/:id/status
      post :status
      # /friends/:id/
      delete :destroy
    end
  end
end

對應路徑如下:

           Prefix Verb   URI Pattern                   Controller#Action
confirmed_friends GET    /friends/confirmed(.:format)  friends#confirmed
    status_friend POST   /friends/:id/status(.:format) friends#status
           friend DELETE /friends/:id(.:format)        friends#destroy
          friends GET    /friends(.:format)            friends#index
                  POST   /friends(.:format)            friends#create
       new_friend GET    /friends/new(.:format)        friends#new
      edit_friend GET    /friends/:id/edit(.:format)   friends#edit
                  GET    /friends/:id(.:format)        friends#show
                  PATCH  /friends/:id(.:format)        friends#update
                  PUT    /friends/:id(.:format)        friends#update
                  DELETE /friends/:id(.:format)        friends#destroy

namespace 與 scope

namespace => 會讓後面指定的資源除了加到路徑上之外也多加到 prefix 及 controller 的名稱上
scope => 只有將資源加到路徑

Rails.application.routes.draw do
  namespace :users do
    resources :articles
  end

  scope :users do
    resources :articles
  end
end

產生路徑如下,可以看到兩種的差異在於用 namespace 的會影響到 prefix 及 controller 的設計,如果有這樣需求的就可以這樣使用,路徑是都一樣的。

# namespace
            Prefix Verb   URI Pattern                        Controller#Action
    users_articles GET    /users/articles(.:format)          users/articles#index
                   POST   /users/articles(.:format)          users/articles#create
 new_users_article GET    /users/articles/new(.:format)      users/articles#new
edit_users_article GET    /users/articles/:id/edit(.:format) users/articles#edit
     users_article GET    /users/articles/:id(.:format)      users/articles#show
                   PATCH  /users/articles/:id(.:format)      users/articles#update
                   PUT    /users/articles/:id(.:format)      users/articles#update
                   DELETE /users/articles/:id(.:format)      users/articles#destroy
----------------------------------------------------------------------------------------------
# scope
            Prefix Verb   URI Pattern                        Controller#Action
          articles GET    /users/articles(.:format)          articles#index
                   POST   /users/articles(.:format)          articles#create
       new_article GET    /users/articles/new(.:format)      articles#new
      edit_article GET    /users/articles/:id/edit(.:format) articles#edit
           article GET    /users/articles/:id(.:format)      articles#show
                   PATCH  /users/articles/:id(.:format)      articles#update
                   PUT    /users/articles/:id(.:format)      articles#update
                   DELETE /users/articles/:id(.:format)      articles#destroy

參考資料:

  1. 為你自己學 Ruby on Rails
  2. Rails Guide

上一篇
Day 16 - 進入Rails世界必須懂:Routes (上)
下一篇
Day 18 - 進入Rails世界必須懂:Controller 及 View
系列文
一探紅寶石的神秘面紗 - Ruby 及 Rails入門介紹 系列30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言