3

假设我有一条路线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等但没有奏效。)

长话短说

怎么做才能让 Rails{ year: ..., month: ..., slug: ...}在传递@postpost_path(而不是 eg @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

也许会有所帮助。

4

1 回答 1

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

您可以参考此 apidock 链接以获取更多信息

于 2013-07-10T21:46:52.880 回答