将对象作为路径助手的参数传递

时间:2013-07-10 21:13:54

标签: ruby-on-rails ruby routes

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

长话短说

在将{ 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

也许会有所帮助。

1 个答案:

答案 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了解更多信息