Ruby on Rails :: Restful URL Customizing

Posted by PunNeng, Sun Sep 02 19:52:00 UTC 2007

อีกหนึ่งส่วนสำคัญของเรื่องนี้ คือ url ของการใช้งาน restful ของ rails
ลองอ่าน restful ของ rails ก่อน ผมติดไว้ว่าจะเขียนเรื่อง routing ไว้ ก็จะเขียนต่อตรงนี้เลยละกัน

หลังจากที่ประกาศ

map.resources :products

ใน config/route.rb แล้ว จะมีชื่อของ route ที่ถูกสร้างไว้เพียบเลย แต่ที่ใช้บ่อยๆ กับ CRUD คร่าวๆ ตามนี้

  • products_path (get -> index) # /products
  • products_path (post -> create) # /products
  • product_path(:id) (get -> show) # /products/:id
  • product_path(:id) (put -> update) # /products/:id
  • product_path(:id) (delete -> destroy) # /products/:id
  • new_product_path (get -> new) # /products/new
  • edit_product_path (get -> edit) # /products/:id;edit

ซึ่งจริงๆ แล้ว _path ก็จะมี _url ไว้ให้เรียกใช้อีกชุดนึง

สำหรับการ map เข้าในแต่ละ action จะทำได้ด้วยการกำหนด request method

Get (Read)

จะใช้ get สำหรับการ request ขอข้อมูล

link_to "List Products", products_path
link_to @product.title, product_path(@product)

ปกติจะใช้กับ link

Post (Create)

จะใช้ post สำหรับการสร้าง หรือการเพิ่มเข้าฐานข้อมูล

<% form_for(:product, :url => products_path) do |f| %>

ปกติจะใช้กับ form

Put (Update)

จะใช้ put สำหรับการปรับปรุงข้อมูลที่มีอยู่แล้ว

<% form_for(:product, :url => product_path(@product), :html => { :method => :put }) do |f| %>

ปกติใช้กับ form เช่นกัน

Delete (Delete)

จะใช้ delete สำหรับการลบ

<%= link_to 'Destroy', product_path(product), :confirm => 'Are you sure?', :method => :delete %>

จริงๆ ไม่จำเป็นเท่าไหร่ว่า method อันไหน ใช้กับอะไร เพียงแต่ใส่ method ให้ได้ ก็ใช้ได้เหมือนๆ กัน

ต่อไป จะทำการกำหนด action ที่นอกเหนือจาก CRUD
ซึ่งผมเคยเขียนไปครั้งนึงแล้ว ลองหยิบตัวอย่างมาสองสามอันที่ใช้บ่อยๆ ละกัน

map.resources :messages, :path_prefix => "/threads/:thread_id"
# --> GET /threads/7/messages/1

หรือใช้ nest

map.resources :threads do |thread| thread.resources :messages end

เวลาเรียกใช้ จะเรียกแบบนี้

<%= link_to @message.title, message_path(@thread, @message) %>
<%= link_to "Message List", messages_path(@thread) %>
<%= link_to @message.title, message_path(:thread_id => @thread, :id => @message.id) %>
<%= link_to "Message List", messages_path(:thread_id => @thread) %>

ยืดหยุ่นสุดๆ อยากใช้แบบไหน ก็ได้เหมือนๆ กัน ถ้าใส่ instance ลงไป ก็จะยิงไปที่ id อัตโนมัติ หรือถ้าเป็นค่าอื่น ก็ระบุไป ถ้าไม่ระบุ ก็เป็น id

ข้อสังเกตอีกนิดนึง คือการระบุให้เป็น singular/plural ถ้าเป็น singular ก็ต้องระบุไป ว่าอันไหน ถ้าไม่ต้องการทำกับ instance ตัวไหนตัวนึงหรือต้องการทำทีละหลายๆ ตัว ก็ระบุเป็น plural ไป จริงๆ เรื่องนี้ใช้ความเข้าใจเอาก็ได้ เพราะมันก็เหมือนๆ english นั่นแหละ :)

map.resources :messages, :collection => { :rss => :get }
# --> GET /messages;rss (maps to the #rss action)
# also adds a url named "rss_messages"

:collection ไว้ใช้กับ plural
วิธีใช้

<%= link_to "RSS", rss_messages_path %> # --> GET /messages;rss (maps to the #rss action)

จะเซ็ตเป็น post ก็ได้ แล้วใส่ที่ form ก็ได้เหมือนๆ กัน สำหรับตัวอย่างการใช้งานกับ form ดูได้จากการที่ใช้ scaffold_resource สร้างมาให้ก็ได้

map.resources :messages, :member => { :mark => :post }
# --> POST /messages/1;mark (maps to the #mark action)
# also adds a url named "mark_message"

คราวนี้ ไว้ใช้กับ singular เช่น

<% form_for :message, @message, :url => :url => mark_message_path(@message) do |f| %>

ผมขี้เกียจละ ตัวอย่างที่่เหลือ คิดว่าคงจะพอเข้าใจอะไรลางๆ แล้วละครับ

map.resources :messages, :new => { :preview => :post }
# --> POST /messages/new;preview (maps to the #preview action)
# also adds a url named "preview_new_message"

map.resources :messages, :new => { :new => :any, :preview => :post }
# --> POST /messages/new;preview (maps to the #preview action)
# also adds a url named "preview_new_message"
# --> /messages/new can be invoked via any request method

map.resources :messages, :controller => "categories",
:path_prefix => "/categories/:category_id",
:name_prefix => "categories_"
# --> GET /categories/7/messages/1
# has named route "categories_messages"

อีกนิดนึง ใน rails 2.0 มันเปลี่ยนเครื่องหมายนิดหน่อย จาก /messages;rss เปลี่ยนมาเป็น /messages/rss แทน

ปล. มันมี map.resource อีกตัวนึง แต่ไว้ใช้สำหรับ singleton ซึ่งผมยังไม่เคยใช้เลย

Filed Under: Ruby on Rails | Tags: howto rest restful route ruby on rails simply restful url

Comments

Have your say

A name is required. You may use HTML in your comments.




codegent: we're hiring