假设我有一条路线get "/:year/:month/:slug", :as => :post"
。为了使其工作,我已经将以下方法添加到Post
类:
def to_param
slug
end
现在,如果我想使用post_path
路由助手,我必须传递3个参数,例如:post_path({ year: '2013', month: '07', slug: 'lorem-ipsum' })
,但由于我不喜欢每次都写它,我已添加另一种方法:
def uri
{ year: self.published_at.strftime('%Y'), month: self.published_at.strftime('%m'), slug: self.slug }
end
它允许我使用post_path(@post.uri)
来获取路径。但它仍然不是我想要的。我想要的是能够在那里传递对象,例如post_path(@post)
,这会给我以下错误:
ActionController::RoutingError: No route matches {:controller=>"posts", :action=>"show", :year=>#<Post id: nil, slug: "lorem-ipsum", title: nil, body: nil, published: nil, published_at: nil, created_at: nil, updated_at: nil>}
可以很容易地推断出Rails真正做的是:post_path({ year: @post })
这显然是错误的。但是,Rails生成的默认路由(仅使用:id
作为参数)在将对象传递给它之后起作用。 Rails如何在内部完成?它是否使用Post
上需要重载的任何隐藏方法? (我已尝试过to_s
,url_options
,id
等等,但都没有效果。)
在将{ year: ..., month: ..., slug: ...}
传递给@post
(而不是post_path
)后,Rails会看到哈希@post.special_method
该怎么办?
来自routes.rb文件的摘录:
scope ':year/:month', :constraints => { year: /\d{4}/, month: /\d{2}/ } do
scope ':slug', :constraints => { slug: /[a-z0-9-]+/ } do
get '/' => 'posts#show', :as => :post
put '/' => 'posts#update'
delete '/' => 'posts#destroy'
get '/edit' => 'posts#edit', :as => :edit_post
end
end
get 'posts' => 'posts#index', :as => :posts
post 'posts' => 'posts#create'
get 'posts/new' => 'posts#new', :as => :new_post
也许会有所帮助。
答案 0 :(得分:0)
尝试将uri方法中的代码移动到to_param。
def to_param
{ year: self.published_at.strftime('%Y'), month: self.published_at.strftime('%m'), slug: self.slug }
end
根据Rails APidock,url_for方法在传入的对象上调用to_param,默认情况下是id。
<%= url_for(@workshop) %>
# calls @workshop.to_param which by default returns the id
# => /workshops/5
您可以参考this apidock link了解更多信息