2010-01-08 31 views
6

Tôi đã có một blogs_controller với một nguồn tài nguyên Blog, vì vậy tôi đã có tuyến đường điển hình của bạn ngay bây giờ như sau:Cách tốt nhất để thực hiện các tuyến đường "/ blog /: năm /: tháng /: ngày /: permalink" trong Rails?

/blogs/new 
/blogs/1 
/blogs/1/edit #etc 

Nhưng đây là những gì tôi muốn:

/blogs/new 
/blogs/2010/01/08/1-to_param-or-something 
/blogs/2010/01/08/1-to_param-or-something/edit #etc 
... 
/blogs/2010/01 # all posts for January 2010, but how to specify custom action? 

tôi biết rằng tôi có thể làm điều này với sự kết hợp của map.resources và map.connect, nhưng tôi có nhiều lượt xem liên kết đến các trang khác thông qua "new_blog_path" v.v ... và tôi không muốn phải chỉnh sửa chúng. Điều này có thể thực hiện với map.resources không? Nó có thể không dễ dàng, nhưng tôi không chống lại việc thông minh. Tôi đã nghĩ đến một cái gì đó như:

map.resources :blogs, :path_prefix => ':year/:month/:day', :requirements => {:year => /\d{4}/, :month => /\d{1,2}/, :day => /\d{1,2}/} 

Nhưng tôi không chắc chắn làm thế nào mà làm việc với những hành động như 'mới' hay 'tạo ra', và nó cũng mang lại cho tôi một con đường như /2010/01/08/blogs/1-to_param-etc với các blog ở giữa URL.

Vì vậy, có một giải pháp thông minh mà tôi đang thiếu hoặc tôi có cần phải đi tuyến đường map.connect không?

Trả lời

13

Tôi chạy vào cùng một vấn đề thời gian gần đây, và, trong khi điều này có thể không được những gì bạn đang tìm kiếm, đây là những gì tôi đã làm để chăm sóc nó:

config/routes.rb :

map.entry_permalink 'blog/:year/:month/:day/:slug', 
        :controller => 'blog_entries', 
        :action  => 'show', 
        :year  => /(19|20)\d{2}/, 
        :month  => /[01]?\d/, 
        :day  => /[0-3]?\d/ 

blog_entries_controller.rb:

def show 
    @blog_entry = BlogEntry.find_by_permalink(params[:slug]) 
end 

blog_entries_helper.rb:

def entry_permalink(e) 
    d = e.created_at 
    entry_permalink_path :year => d.year, :month => d.month, :day => d.day, :slug => e.permalink 
end 

_entry.html.erb:

<h2><%= link_to(entry.title, entry_permalink(entry)) %></h2> 

và vì lợi ích của sự hoàn chỉnh:

blog_entry.rb:

before_save :create_permalink 

#... 

private 

def create_permalink 
    self.permalink = title.to_url 
end 

Phương pháp #to_url xuất phát từ số Stringex của rsl.

Tôi vẫn còn mới đối với Rails (và lập trình), nhưng đây có lẽ là cách đơn giản nhất để thực hiện. Đây không phải là một cách RESTful để đi về những thứ để bạn không đạt được lợi ích của map.resources, thật không may.

Tôi không chắc chắn (vì tôi chưa thử), nhưng bạn có thể tạo người trợ giúp thích hợp trong application_helper.rb để ghi đè người trợ giúp tuyến đường mặc định cho blog_path, et al. Nếu điều đó hoạt động, thì bạn sẽ không phải thay đổi bất kỳ mã xem nào của mình.

Nếu bạn cảm thấy mạo hiểm, bạn có thể xem Routing Filter. Tôi đã xem xét việc sử dụng nó, nhưng nó có vẻ như quá mức cần thiết cho nhiệm vụ này.

Ngoài ra, nếu bạn không biết, có hai điều bạn có thể làm để kiểm tra lộ trình của bạn/đường dẫn từ bên trong kịch bản/console:

rs = ActionController::Routing::Routes 
rs.recognize_path '/blog/2010/1/10/entry-title' 

app.blog_entry_path(@entry) 

Chúc may mắn!

+0

Xin cảm ơn Jay, đây là một bản viết rất hay đã giúp tôi tiết kiệm rất nhiều thời gian ngay hôm nay! –

+0

Giải thích tuyệt vời! –

+0

Phiên bản tuyến đường ray 3 sẽ là gì? – sguha

2

Từ API Docs:

map.connect 'articles/:year/:month/:day', 
      :controller => 'articles', 
      :action  => 'find_by_date', 
      :year  => /\d{4}/, 
      :month  => /\d{1,2}/, 
      :day  => /\d{1,2}/ 

Sử dụng các tuyến đường trên, URL "localhost: 3000/bài báo/2005/11/06" bản đồ để

params = { :year => '2005', :month => '11', :day => '06' } 

Hình như bạn muốn làm cùng một điều, nhưng hậu tố một slug bài. Liên kết mới và chỉnh sửa của bạn sẽ vẫn là liên kết "trường học cũ", như "localhost: 3000/articles/1/edit" và "localhost: 3000/articles/new". Chỉ cần liên kết "hiển thị" mới được cập nhật.

+0

hey jarrett, cảm ơn bài đăng. slug là không có vấn đề, to_param có thể chăm sóc đó. Những gì tôi thực sự muốn làm là thoát khỏi 'map.connect' và xử lý điều này trong một cuộc gọi đến 'map.resources' vì vậy tôi không cần phải sửa đổi tất cả các cuộc gọi hiện tại của tôi thành blog_path (@blog) vv. Tôi muốn gọi url_for (@blog) và lấy lại một cái gì đó như '/ blog/2010/01/08/1-to_param-hoặc-something' mà tôi tưởng tượng là không thể với map.connect. Tôi đoán những gì tôi muốn là không thể (là định dạng url này RESTful anyway?), Tôi chỉ cố gắng để xem nếu ai có bất kỳ giải pháp sáng tạo. – carpeliam

Các vấn đề liên quan