October 1, 2023

Viiisit [Ruby on Rails] - Route!

#ruby on rails

今天來點 Routes

https://ithelp.ithome.com.tw/upload/images/20230930/20161764YQPprUetsK.png

Viiisit Ruby on Rails - CoC & DRY!
有提到 REST 與 RESTful 概念,我們再複習一次:

REST

REST (Representational State Transfer) 是一種軟體架構風格,
主要用於設計網路應用程式的 API(幫助世界各地不同軟體、程式在網際網路中能夠互相傳遞訊息)
它基於資源(Resource)的概念,每個資源都有唯一的識別符號(URI),
並且可以透過不同的 HTTP 方法(GET、POST、PUT、DELETE 等)來執行相應的操作。

每個網頁都可視為一個資源提供使用者使用,而我們就可以透過 URL,也就是這些資源的地址,
來取得這些資源並在瀏覽器上使用。
Remark:
URI - Uniform Resource Identifier,
其中最常看見的 URL 是 URI 的一種特殊形式,兩者都是用來唯一識別資源的地址。

RESTful

透過 Rails 的路徑設定,可以快速地建立符合 RESTful 概念的路由,並使應用程序遵循 RESTful 架構來處理資源的 CRUD 操作。

RESTful 是符合 REST 設計原則的 API。當我們在設計 API 時,遵循 REST 的原則,特別是適當地使用 HTTP 方法、URI 和回應狀態碼,我們就可以稱這個 API 為 RESTful API。

Remark:
所謂的 API 是應用程式介面 (application programming interface),
網址也是一種應用程式的「介面」,故稱為 API。
RESTful 風格的網址設計強調從路由結構就能看出要對什麼資料、進行什麼操作。

Ruby on Rails 在設計上已經將 RESTful 的路由設定架構出來了。透過 Rails 的路徑設定,可以快速地建立符合 RESTful 概念的路由,並使應用程序遵循 RESTful 架構來處理資源的 CRUD 操作。

CRUD

CRUD 是 Create, Read, Update, Delete 四個字母的縮寫,中文是「增刪查改」;
這是一連串常見的動作行為,通常是為了針對某個特定資源所作出的舉動,如:建立資料、讀取資料等。
這四個行為最常見的用途是在使用 SQL 資料庫網站的 API 埠口的時候。

相對應的 SQL 語法、HTTP 請求、REST 表現層狀態轉換

- SQL HTTP REST 表現層狀態轉換
Create 建立 INSERT PUT / POST POST
Read 讀取 SELECT GET GET
Update 更新 UPDATE PUT / POST / PATCH PUT
Delete 刪除 DELETE DELETE DELETE

建立 Route

首先,要把路徑建立起來,才能通過這些路徑來對應各個頁面。
因為 Route 是整個網站連結各個頁面的相關路徑,當使用者連上網站時,Rails 會解析使用者所輸入的網址及參數,去找到該負責處理 Controller 與 Action。

實作 GO! GO!

在 routes.rb 這個檔案裡,把所需要的路徑先建立起來!

config/routes.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Rails.application.routes.draw do
# ⓶ 建立 homepage (Method 1) -> 文章列表直接當首頁使用
get '/', to: 'articles#index'
# ⓶ 建立 homepage (Method 2) 可以直接以 root 'controller#action'
root 'articles#index'

# ⓵ 建立 articles indexpage -> 文章列表
get '/articles', to: 'articles#index'
# ⓷ 建立 articles newpage -> 新增文章(呈現填寫的表單)
get '/articles/new', to: 'articles#new'
# ⓸ 新增文章(按下新增按鈕會提交的行為)
post '/articles', to: 'articles#create'

# show, edit, update, delete 都是透過尋找 id 來找對應的文章!
# 這必須被放在 articles newpage 之後,因為這是屬於比對型的路徑,
# 如果放在 articles newpage 之前, '/articles/new' /new 會被當作 /:id。
# 要注意!`:id` 並非符號,是一個 params 可以拿來當作 key 的寫法
# ⓹ 建立 articles showpage -> 呈現每一篇文章的相關資訊,透過自定義路徑建立對應的 view
get '/articles/:id', to: 'articles#show', as: "article" # as: "自定義名字";可以生成 "自定義名字"_path
# ⓺ 建立 articles editpage
get '/articles/:id/edit', to: 'articles#edit', as: "edit_article"
# ⓻ 更新文章(按下更新按鈕會提交的行為)
patch '/articles/:id', to: 'articles#update'
# ⓼ 刪除文章(按下刪除按鈕會提交的行為)
delete '/articles/:id', to: 'articles#destroy'
end

註解拿掉,並將首頁路徑以 root 'articles#index' 作為代表:

1
2
3
4
5
6
7
8
9
10
11
12
Rails.application.routes.draw do
root 'articles#index'

get '/articles', to: 'articles#index'
get '/articles/new', to: 'articles#new'
post '/articles', to: 'articles#create'

get '/articles/:id', to: 'articles#show', as: "article"
get '/articles/:id/edit', to: 'articles#edit', as: "edit_article"
patch '/articles/:id', to: 'articles#update'
delete '/articles/:id', to: 'articles#destroy'
end

Remark:
可以將常用的 route 放在前面,不常用的放在後面,因為 route 在讀取時,越前面的會越先讀取!

快速捷徑! -> resources

上方的路徑可以透過 resources :自定義名字 讓 Rails 框架自動生成!

config/routes.rb

1
2
3
4
Rails.application.routes.draw do
root 'articles#index'
resources :articles
end

resource’s’ - s 的有無差異在生成的路徑中是否包含 :id 參數!
透過有 :id 可以針對特定的資料進行操作。

巢狀式的路徑

resources 方法裡面可以再繼續包 resources,例如一個 article 可能會有很多 comments:

1
2
3
resources :articles do
resources :comments
end

透過上述方式可以生成主從關係的路徑,
但在這之中有些路徑其實不需要透過 articles 來找到 comments,
可以直接透過他自己的 :id 找到,因此,可以將路徑限制一些條件:

1
2
3
4
5
6
7
8
9
10
resources :articles do
# resources :comments, only: [:index, :new, :create]
# :index, :new 是跟 article 的 :index, :new 相同頁面,這裡就不需要寫!
resources :comments, only: [:create]
end

# 這些不需要跟 articles 有主從的路徑關係,只需要單就 comment :id 去搜尋即可!
# resources :comments, only: [:show, :edit, :update, :destroy]
# :show, :edit, :update 這裡不需要寫(主要也是看開發需求),comment 不需要單獨 show 出來!
resources :comments, only: [:destroy]

註解拿掉:

1
2
3
4
5
resources :articles do
resources :comments, only: [:create]
end

resources :comments, only: [:destroy]

而,這樣的寫法還可以透過 Rails 提供的 Shallow Nesting 方法來簡化:

Shallow Nesting

Shallow Nesting 是在設計 Rails 路徑時的一種方式,
目的是將深度嵌套的路徑結構簡化,使路徑設定更加直觀和易於管理。

在下方如果不寫 only: [:create, :destroy],預設情況下所有的 CRUD
(create、read、update、destroy)都會被定義在 comments routes 範圍內。
在這裡,我只想要有新增評論跟刪除評論的功能。

1
2
3
resources :articles do
resources :comments, shallow: true, only: [:create, :destroy]
end

collection vs member

藉由 resources 可以快速生成 8 個基本路徑,但是,我還想要更多不同的路徑該怎麼辦?
可以使用 collection 或 member 選項來定義額外的自訂路徑!
這些自訂路徑可以對應到控制器中定義的自訂動作(action),能處理更多不同的用途。

這兩種路徑的主要差異在於生成的 URL 有無 :id。

collection

使用 collection 選項可以定義針對集合進行操作的路徑,
也就是不針對單一資源,而是針對多個資源進行操作。

1
2
3
4
5
6
7
resource :users, except: [:show, :destroy] do
collection do
get :login # GET /users/login:顯示登入表單的頁面
post :afterlogin # POST /users/afterlogin:處理登入表單的提交
delete :logout # DELETE /users/logout:執行登出操作
end
end

member

使用 member 選項可以定義針對單一資源進行操作的路徑,路徑內會包含資源的(ID)。

1
2
3
4
5
resources :articles, only: [] do
member do
patch :like # PATCH /articles/:id/like
end
end

這段使用 resources 方法來生成對文章資源的路徑,但是通過 only: [] 選項,只生成一個空的資源路徑,即不生成標準的 CRUD 路徑。在 member 區塊中使用 patch 方法,指定了一個名為 like 的自定義動作,並將這個動作與單一文章資源(即 /articles/:id)相關聯。這樣就生成了一個特定的路徑,用於對單一文章進行點讚(like)操作。


參考資料:
增刪查改
為你自己學 Ruby on Rails - Routes