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 ซึ่งผมยังไม่เคยใช้เลย