简体   繁体   English

自定义RESTful资源的url_for(复合键;不仅仅是id)

[英]url_for of a custom RESTful resource (composite key; not just id)

Given the following resource definition: 给定以下资源定义:

map.resources :posts, :except => [:show]
map.post '/:year/:month/:slug, :controller => :posts, :action => :show

I can make url_for work for me, using this syntax: 我可以使用以下语法让url_for为我工作:

<%= link_to @post.title, post_url(:year => '2010', :month => '02', :slug => 'test') %>

But is there a way to make this work? 但有没有办法让这项工作?

<%= link_to @post.title, @post %>

Currently it throws this error: 目前它抛出此错误:

No route matches {:year=>#<Post id: 1, title: "test", (...)>, :controller=>"posts", :action=>"show"}

Apparently it passes the @post object to the first route parameter (seems like a Rails bug...). 显然它将@post对象传递给第一个路由参数(看起来像是一个Rails错误...)。 But can I make this work for me? 但我可以为我做这项工作吗? I'll add that messing with default_url_options is a dead end. 我要补充说,使用default_url_options搞乱是一个死胡同。

Solution working only in Rails 3.x is ok, but I would prefer not to use any plugins. 仅在Rails 3.x中工作的解决方案是可以的,但我不想使用任何插件。

Override to_param . 覆盖to_param The default value for to_param is the record ID, but you can change that. to_param的默认值是记录ID,但您可以更改它。

class Post
  def to_param
    "/#{year}/#{month}/#{slug}"
  end
end

(This assumes you have methods in the Post class for year , month and slug .) (这假设您在Post类中yearmonthslug 。)

Now when URLs are generated, your overridden to_param will be called. 现在,当生成URL时,将调用被覆盖的to_param

<%= link_to @post.title, @post %> 
    => <a href="/2010/02/foobar">Foobar</a>

Obviously you must ensure your PostsController show action can find the record based on the parameters it is passed. 显然,你必须确保你的PostsController show动作可以根据传递的参数找到记录。

You may need to change your route definition and eliminate this route: 您可能需要更改路径定义并消除此路线:

map.post '/:year/:month/:slug, :controller => :posts, :action => :show

However, with to_param overridden, the default RESTful post_path will work just fine for the URLs you want to generate. 但是,通过覆盖to_param ,默认的RESTful post_path对于您要生成的URL可以正常工作。

How about fixing url_for for the PostsController ? 如何修复PostsController url_for May not be very elegant but it is DRY and things should just work. 可能不是很优雅,但它是干的,事情应该工作。

# 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

Unfortunately, when you pass an ActiveRecord to link_to , it tries to use Polymorphic URL helpers to generate the URL for the link. 不幸的是,当您将ActiveRecord传递给link_to ,它会尝试使用Polymorphic URL帮助程序来生成链接的URL。

The Polymorphic URL helpers are only designed to generate RESTful URLs by using the record identifier of your ActiveRecord. Polymorphic URL帮助程序仅用于通过使用ActiveRecord的记录标识符生成RESTful URL。

Since your route uses multiple attributes of the Post object, the Polymorphic URL helpers are not equipped to generate the correct URL... not so much a bug as a limitation :) 由于您的路由使用Post对象的多个属性,因此Polymorphic URL帮助程序无法生成正确的URL ...而不是作为限制的错误:)

Delving into link_to , when you pass it a Hash, it doesn't use Polymorphic Routing, so you avoid the whole problem. 深入研究link_to ,当你传递哈希时,它不使用多态路由,因此你可以避免整个问题。

I suppose a hacky approach would be to define a method on Post called routing_hash which returns 我想一个hacky方法是在Post上定义一个返回的方法,叫做routing_hash

(:year => post.year, :month => post.month, :slug => post.slug)

I appreciate that it's not a DRY approach, but it's the best I can come up with at the moment 我很欣赏它不是干眼的方法,但它是我现在能想到的最好的方法

I was trying out TempoDB and extending their class with the below worked for me. 我正在尝试TempoDB并扩展他们的课程,下面为我工作。 I had the route "resources :series" and then could use url_for with no problem. 我有路由“资源:系列”,然后可以使用url_for没有问题。

class TempoDB::Series
  def self.model_name
    ActiveModel::Name.new(TempoDB::Series,nil,'series')
  end
  def to_param
    self.key
  end
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM