เปลี่ยนชื่อของพารามิเตอร์: id ในการกำหนดเส้นทางทรัพยากรสำหรับ Rails


108

ฉันมองไปรอบ ๆ เกี่ยวกับวิธีการเปลี่ยนสล็อตพารามิเตอร์แบบไดนามิกและพบว่าโพสต์นี้ทำสิ่งที่แน่นอน โพสต์คือhttps://thoughtbot.com/blog/rails-patch-change-the-name-of-the-id-parameter-in

โดยทั่วไปสิ่งที่ทำคือเส้นทางต่อไปนี้:

map.resources :clients, :key => :client_name do |client|
  client.resources :sites, :key => :name do |site|
    site.resources :articles, :key => :title
  end
end

เส้นทางเหล่านี้สร้างเส้นทางต่อไปนี้:

/clients/:client_name
/clients/:client_name/sites/:name
/clients/:client_name/sites/:site_name/articles/:title

วิธีแก้ปัญหาอย่างหนึ่งคือการลบล้างdef to_paramเมธอดในโมเดล แต่ฉันต้องการสิ่งนี้โดยไม่ต้องสัมผัสโมเดลนั้นเอง

แต่เนื่องจากเป็น Rails 2.x ฉันจะทำสิ่งเดียวกันกับ Rails 3 ได้อย่างไร

อัปเดต

แอพนี้ใช้ Mongoid ไม่ใช่ AR ดังนั้นอัญมณีที่เป็นมิตรจึงไม่สามารถใช้ afaik ได้

คำตอบ:


192

ราง 4 และ 5

ใน Rails 4 มีการ:paramเพิ่มตัวเลือกซึ่งดูเหมือนว่าจะทำในสิ่งที่คุณกำลังมองหา คุณสามารถใช้เวลาดูที่Rails 3 รหัสเมื่อเทียบกับทางรถไฟ 4 รหัส

รายละเอียด

คุณสามารถใช้สิ่งนี้ในroutes.rbไฟล์ของคุณได้อย่างง่ายดาย:

# config/routes.rb

resources :posts, param: :slug

# app/controllers/posts_controller.rb

# ...
@post = Post.find_by(slug: params[:slug])
# ...

ในฐานะของการเปิดตัวของทางรถไฟ 4 ฟังก์ชั่นนี้ถูกบันทึกไว้ในคู่มือการรถไฟ

ราง 3

น่าเสียดายที่ใน Rails 3 :keyตัวเลือกสำหรับresourcesถูกลบออกไปแล้วดังนั้นคุณจึงไม่สามารถเปลี่ยนชื่อของเส้นทางที่สร้างด้วยวิธีนี้ได้ง่ายๆอีกต่อไปเพียงแค่ส่งตัวเลือกเสริม

รายละเอียด

ผมถือว่าคุณได้แล้วอากาศอย่างใดการประยุกต์ใช้วิธีการทำงานที่คุณต้องการในปีที่ผ่านมา แต่ผมจะไปเป็นวิธีการที่จะได้รับผลที่คุณอธิบายใน Rails routes.rb3 มันจะเกี่ยวข้องกับการทำงานมากกว่าto_paramวิธีการเล็กน้อย คุณยังสามารถกำหนดค่าพารามิเตอร์ที่กำหนดเองในเส้นทางที่กำหนดโดยใช้scopeและmatch(หรือเป็นของญาติget, put, postและdelete) คุณเพียงแค่เขียนชื่อพารามิเตอร์ที่คุณต้องการในตัวจับคู่:

get 'clients/:client_name', :to => 'clients#show', :as => client

scope 'clients/:client_name' do
  get 'sites/:name', :to => 'sites#show', :as => site
end

คุณจะต้องเพิ่มเส้นทางทั้งหมดที่resourcesสร้างขึ้นโดยอัตโนมัติสำหรับคุณด้วยตนเองแต่มันจะบรรลุสิ่งที่คุณกำลังมองหา คุณยังสามารถใช้:controllerตัวเลือกscopeและscopeบล็อกเพิ่มเติมได้อย่างมีประสิทธิภาพเพื่อกำจัดการทำซ้ำบางส่วน


แก้ไข (8 พฤษภาคม 2014):ทำให้ชัดเจนยิ่งขึ้นคำตอบมีข้อมูลสำหรับทั้ง Rails 3 & 4 อัปเดตลิงก์ไปยังรหัสเพื่อไปยังหมายเลขบรรทัดที่แน่นอนและคอมมิตเพื่อให้ใช้งานได้นานขึ้น

แก้ไข (16 พฤศจิกายน 2014): Rails 4 ควรอยู่ที่ด้านบนสุดในขณะนี้และรวมข้อมูลที่เกี่ยวข้องเนื่องจากเป็นเวอร์ชันปัจจุบันของ Rails มาระยะหนึ่งแล้ว

แก้ไข (9 ส.ค. 2016):สะท้อนให้เห็นว่าโซลูชันยังคงใช้งานได้ใน Rails 5 และอัปเดตลิงก์ที่ล้าสมัย


1
โดยพื้นฐานแล้ว Rails3 ได้สร้างตัวเลือกทรัพยากรในเราเตอร์เพื่อให้พักผ่อนได้เต็มที่ แต่จำเป็นต้องถูกแทนที่เพื่อประโยชน์ในการมีชื่อตัวแปรที่กำหนดเอง ... รู้สึกง่อย!
Augustin Riedinger

1
นี่คือparam
แบ็

สิ่งนี้จะทำให้ตัวช่วย url แตก พวกเขาสร้างเส้นทางตาม id ปกติถ้าฉันส่งวัตถุเข้ามาหรือบ่นเกี่ยวกับคีย์ [: slug] ที่หายไปถ้าฉันส่งกระสุนเข้ามามีความคิดอย่างไรในการแก้ไข
RonLugge

9
FYI หากคุณใช้รีซอร์สที่ซ้อนกันพารามิเตอร์สำหรับทรัพยากรพาเรนต์จะเป็นpost_slugซึ่งอาจทำให้สับสนได้
ghayes

4
นี่เป็นสิ่งที่ดีจริงๆ แต่ฉันจะทำอย่างไรถ้าฉันไม่ต้องการชื่อพารามิเตอร์ของรหัสหลักเช่น post_post_id สำหรับทรัพยากรที่ซ้อนกัน
Asnad Atta

45

ใน Rails 4 ให้ส่งผ่านตัวเลือกพารามิเตอร์เพื่อเปลี่ยนพารามิเตอร์: id ตัวอย่างเช่น resources :photos, param: :photo_nameจะสร้าง / photos /: photo_name


1

ถ้าฉันเข้าใจคุณถูกต้องสิ่งที่คุณต้องการคือมีclient_nameแทนidใน url ของคุณใช่ไหม

คุณสามารถทำได้โดยการลบล้างto_paramเมธอดในโมเดลของคุณ คุณจะได้รับข้อมูลเพิ่มเติมที่นี่


1
ดังที่ได้กล่าวไปแล้วว่าฉันมีข้อ จำกัด ในการไม่เปลี่ยนโมเดล ตัวอย่างข้างต้นไม่รองรับหรือเลิกใช้งานใน Rails 3 หรือไม่?
Autodidact

1

มีอัญมณีสำหรับสิ่งนั้นเช่นเดียวกับที่มีอัญมณีสำหรับทุกสิ่ง)

ฉันใช้FriendlyIdสำหรับพฤติกรรมแบบนี้ในราง 3

คุณจะต้องเพิ่มรหัสบางอย่างในแบบจำลองของคุณเช่นนี้:

class Client < ActiveRecord::Base
  has_friendly_id :name
end

... และถ้าลูกค้าของคุณไม่ได้มีชื่อเข้ากันได้ URI has_friendly_id :name, :use_slug => trueคุณอาจต้องการที่จะใช้กระสุนสำหรับว่าที่คุณสามารถทำอะไรกับ เมื่อใช้ทากคุณจะต้องคงอยู่ในฐานข้อมูลด้วยเช่นกัน

และเป็นที่กล่าวถึงแล้วคุณยังสามารถใช้to_paramเคล็ดลับกับรางที่ 3 เป็นเอกสารที่นี่ ฉันคิดว่า FriendlyId ค่อนข้างหลากหลายกว่า


ฉันชอบรหัสที่เป็นมิตรและใช้ในหลายโครงการ จริงๆแล้วแอพของฉันใช้ Mongoid และ friendly_id ไม่สนับสนุน afaik และอย่างที่ฉันได้กล่าวไปแล้วว่าข้อ จำกัด ของฉันคือการไม่เปลี่ยนโมเดล
Autodidact

1
หากคุณใช้ mongoid จะมีmongoid-slugสำหรับการใช้งานฟังก์ชันนี้ มันใช้งานได้จริงto_paramแต่ก็ทำสิ่งที่ชาญฉลาดอื่น ๆ อยู่เบื้องหลังเช่นกัน ฉันพบลิงค์ที่นี่: stackoverflow.com/questions/4744446/…
Frost

ฉันชอบอัญมณีนั้น มีอีกหนึ่งที่คล้ายกันคือslugoid แต่อย่างที่บอกไปว่าฉันมีข้อ จำกัด ในการไม่ปรับเปลี่ยนโมเดล ที่to_paramแบ่งส่วนหน้าของแอปของฉัน อันที่จริงฉันกำลังมองหาแนวทางการกำหนดเส้นทางอย่างสิ้นหวังคือฉันจะเปลี่ยน API ของฉัน แต่ไม่ทำลายส่วน Model และส่วนหน้าออกจากแอป ทำไมฉันไม่สามารถปรับเปลี่ยนเส้นทางได้ตามที่ระบุไว้เท่านั้นและโพสต์ตัวอย่างสำหรับรางรุ่นเก่าด้านบน ???
Autodidact

คุณได้พยายามเขียนตัวควบคุมใหม่เพื่อให้ใช้คีย์เส้นทางที่คุณกำหนดเองหรือไม่? ตัวอย่างเช่น@client = Client.find(:name => param[:client_name]ในClientsController#show? นั่นอาจได้ผล
Frost

Client.where(:name => param[:client_name]).first, นั่นคือ.
Frost

0

ใน Rails 3 คุณสามารถเปลี่ยนชื่อคีย์ id โดยใช้เนมสเปซและขอบเขตเช่นนี้ร่วมกัน (ไม่ค่อยดีนัก):

namespace :clients do
  scope "/:client_name" do
    namespace :sites do
      scope "/:name" do
         post "/:title" => "articles#create"
         ...
      end
    end
  end
end
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.