Routing สำหรับ Rails กับการกำหนด Path อย่างง่ายให้ Resources

โดย นางสาวแสงเดือน จันทร์ใหม่ – 16 ก.ค. 2558


Routing for Resources

Routing หรือการกำหนด route ให้ resources สำหรับ rails นั้นทำได้ง่ายๆ โดยการกำหนดค่าที่ไฟล์ routes.rb ในแอพพลิเคชั่น

ซึ่งใน rails จะทำทำการ maps ระหว่าง HTTP เมธอด กับ action ของ controller ตาม route ที่เรากำหนด

เราสามารถกำหนด route ได้ดังนี้

[code language="ruby"]
resources :recipes
[/code]

โดยค่า default ของ rails เมื่อประกาศ route ดังตัวอย่าง จะทำการ maps กับ method ของ controller 7 methods ด้วยกัน คือ show, index, new, create, edit, update, และ destroy ซึ่งเราสามารถเรียกใช้งานผ่าน HTTP method และ path เพื่อทำงานที่ action ต่างๆ ของ controller ได้ดังนี้

HTTP method path Controller action
GET /recipes/:id recipes#show
GET /recipes recipes#index
GET /recipes/new recipes#new
POST /recipes recipes#create
GET /recipes/:id/edit recipes#edit
PUT/PATCH /recipes/:id recipes#update
DELETE /recipes/:id recipes#destroy

หากผู้ใช้ไม่ต้องการใช้ method ทั้งหมดตามค่า default ก็สามารถกำหนดได้ว่าต้องการ method อะไรบ้าง หรือไม่ต้องการ method อะไรบ้าง เช่น

[code language="ruby"]
resources :recipes, only: [:show, :index]
[/code]

เพื่อบอกกำหนดว่า recipes สามารถเข้าถึงได้เฉพาะ method show และ index

[code language="ruby"]
resources :recipes, except: [:destroy]
[/code]
เพื่อบอกกำหนดว่า recipes ไม่สามารถเข้าถึง method destroy ได้
นอกจากนี้เรายังสามารถกำหนด route ให้หลายๆ resource พร้อมกันได้
[code language="ruby"]
resources :recipes, :restaurants, :customers
[/code]

Singular Resources

เนื่องจาก Rails เป็นภาษา programming ที่ออกแแบบมาให้อ่านเข้าใจง่าย จึงให้ความสำคัญกับความหมายของคำ โดยเฉพาะคำพหูพจน์และคำเอกพจน์ สำหรับการกำหนด routing ถือว่าสำคัญมาก ซึ่งคำทีมีความหมายเดียวกันแต่เป็นพหูพจน์เมื่อนำมากำหนด route จะได้ดังตัวอย่างก่อนหน้าที่อธิบายไป แต่เมื่อคำความหมายเดิมในรูปเอกพจน์ ใช้กำหนด route จะได้ผลลัพธ์อีกแบบหนึ่งเรียกว่า singular resources

โดยการทำงานจะเหมือนกับการกำหนด route ให้ resources ปกติ มีการ maps ระหว่าง HTTP method และ Controller method เช่นเดียวกัน ที่ต่างกันคือ ค่า default เริ่มต้น จากปกติที่ default เริ่มต้นมี 7 methods แต่ singular จะเหลือ 6 methods ซึ่งจะตัด index ทิ้งไป ตัวอย่างการกำหนด route แบบ singular

[code language="ruby"]
resource :person
[/code]

ซึ่งสามารถเรียกใช้งาน HTTP method และ path เพื่อทำงานที่ action ต่างๆ ของ controller ได้ดังนี้

HTTP method path Controller action
GET /person persons#show
GET /person/new persons#new
POST /person persons#create
GET /person/edit persons#edit
PUT/PATCH /person persons#update
DELETE /person persons#destroy

Nested Resources

Nested Resources เป็นการกำหนด resources ที่อยู่ภายใต้อีก resources หนึ่ง หรือเป็นการกำหนด resources ที่มีความสัมพันธ์ในลักษณะ แม่-ลูก กัน เช่น

[code language="ruby"]
resources :recipes do
 resources :ingredients
end
[/code]

โดยเมื่อต้องการเข้าถึงการใช้งาน method ต่างๆ ใน ingredients สามารถทำได้ดังนี้

HTTP method path Controller action
GET /recipes/:recipe_id/ingredients/:id ingredients#show
GET /recipes/:recipe_id/ingredients ingredients#index
GET /recipes/:recipe_id/ingredients/new ingredients#new
POST /recipes/:recipe_id/ingredients ingredients#create
GET /recipes/:recipe_id/ingredients/:id/edit ingredients#edit
PUT/PATCH /recipes/:recipe_id/ingredients/:id ingredients#update
DELETE /recipes/:recipe_id/ingredients/:id ingredients#destroy

สิ่งสำคัญที่ต้องพิจารณาเมื่อใช้ Nested Resources คือ ความลึกของความสัมพันธ์ที่จะกำหนด เนื่องจาก rails ไม่ได้จำกัดขนาดความลึกของความสัมพันธ์ แต่ความสัมพันธ์ยิ่งลึก Url จะยิ่งยาว ซึ่งความยาวของ Url มีขีดจำกัด ดังนั้น เมื่อต้องใช้ Nested Resources จึงต้องพิจารณาส่วนนี้ให้ดี

การเพิ่ม path เพิ่มเติมจาก RESTful route

แม้ routing ของ rails จะมี default method ที่ครบถ้วนตามการใช้งานพื้นฐานแล้วก็ตาม แต่บ่อยครั้งที่เราจำเป็นต้องสร้าง method เพิ่มเติมเพื่อการทำงานที่ซับซ้อนยิ่งขึ้น จึงต้องมีการกำหนด route เพิ่มเติมให้ resources

โดยลักษณะของ method สำหรับเข้าถึง resources มีลักษณะสำคัญ 2 ประการคือ route ที่ต้องการ id เพื่อเข้าถึง resources และ route ที่ไม่ต้องมี id ก็สามารถเข้าถึง resources ได้

ดังนั้นการเพิ่ม route ที่เหมาะสมจึงทำได้สองวิธี ดังนี้

[code language="ruby"]
resources :products do
 member do
  get price
 end
end
[/code]

member ใช้สำหรับเข้าถึง resources ที่ต้องใช้ id
จากตัวอย่าง สามารถเรียกใช้งานได้ดังนี้

HTTP method path Controller action
GET /products/:id/price products#price
[code language="ruby"]
resources :products do
 collection do
  get my_products
 end
end
[/code]

collection ใช้สำหรับเข้าถึง resources โดยไม่ต้องระบุ id
จากตัวอย่าง สามารถเรียกใช้งานได้ดังนี้

HTTP method path Controller action
GET /products/my_products products#my_products

ซึ่งทั้งหมดนี้เป็นเพียงการใช้งานพื้นฐานอย่างง่าย โดยสามารถศึกษาการใช้งานเพิ่มเติม เพื่องานที่ซับซ้อนมากยิ่งขึ้นได้ที่

http://guides.rubyonrails.org/routing.html