给定以下资源定义:
map.resources :posts, :except => [:show] map.post '/:year/:month/:slug, :controller => :posts, :action => :show
我可以url_for
使用以下语法为我工作:
<%= link_to @post.title, post_url(:year => '2010', :month => '02', :slug => 'test') %>
但有没有办法让这项工作?
<%= link_to @post.title, @post %>
目前它抛出此错误:
No route matches {:year=>#, :controller=>"posts", :action=>"show"}
显然它将@post对象传递给第一个路由参数(看起来像是一个Rails错误...).但我可以为我做这项工作吗?我要补充一点,搞乱default_url_options
是一个死胡同.
仅在Rails 3.x中工作的解决方案是可以的,但我不想使用任何插件.
覆盖to_param
.默认值为to_param
记录ID,但您可以更改它.
class Post def to_param "/#{year}/#{month}/#{slug}" end end
(这假设您在Post
类中有方法year
,month
和slug
.)
现在,当生成URL时,to_param
将调用被覆盖的内容.
<%= link_to @post.title, @post %> => Foobar
显然,你必须确保你的PostsController show动作可以根据传递的参数找到记录.
您可能需要更改路径定义并消除此路线:
map.post '/:year/:month/:slug, :controller => :posts, :action => :show
但是,通过to_param
覆盖,默认RESTful post_path
将适用于您要生成的URL.
如何固定url_for
的PostsController
?可能不是很优雅,但它是干的,事情应该工作.
# app/controllers/posts_controller.rb class PostsController < ApplicationController protected def url_for(options = {} ) if options[:year].class.to_s == "Post" obj = options[:year] options[:year] = obj.year options[:month] = obj.month options[:slug] = obj.slug end super(options) end end