Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 自定义RESTful资源的url_(复合键;不仅仅是id)_Ruby On Rails_Ruby_Rest - Fatal编程技术网

Ruby on rails 自定义RESTful资源的url_(复合键;不仅仅是id)

Ruby on rails 自定义RESTful资源的url_(复合键;不仅仅是id),ruby-on-rails,ruby,rest,Ruby On Rails,Ruby,Rest,给定以下资源定义: map.resources :posts, :except => [:show] map.post '/:year/:month/:slug, :controller => :posts, :action => :show 我可以使用以下语法使的url\u为我工作: <%= link_to @post.title, post_url(:year => '2010', :month => '02', :slug => 'test')

给定以下资源定义:

map.resources :posts, :except => [:show]
map.post '/:year/:month/:slug, :controller => :posts, :action => :show
我可以使用以下语法使的
url\u为我工作:

<%= link_to @post.title, post_url(:year => '2010', :month => '02', :slug => 'test') %>
'2010',:month=>'02',:slug=>'test')%>
但有没有办法让它发挥作用呢

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

当前它抛出以下错误:

No route matches {:year=>#<Post id: 1, title: "test", (...)>, :controller=>"posts", :action=>"show"}
没有路由匹配{:year=>#,:controller=>“posts”,:action=>“show”}
显然,它将@post对象传递给第一个route参数(看起来像Rails bug…)。但我能为自己做这件事吗?我要补充的是,乱动
默认的url\u选项是一条死胡同


仅在Rails 3.x中工作的解决方案是可以的,但我不希望使用任何插件。

不幸的是,当您将ActiveRecord传递到
链接时,它会尝试使用多态URL帮助程序来生成链接的URL

多态URL帮助程序仅用于使用ActiveRecord的记录标识符生成RESTful URL

由于路由使用Post对象的多个属性,因此多态URL帮助程序无法生成正确的URL。。。与其说是一个bug,不如说是一个限制:)

深入研究
link\u to
,当您向其传递哈希时,它不会使用多态路由,因此您可以避免整个问题

我认为一种黑客方法是在Post上定义一个名为
routing\u hash
的方法,该方法返回

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

我很感激这不是一种枯燥的方法,但这是目前我能想到的最好的方法。
to_param
的默认值是记录ID,但您可以更改它

class Post
  def to_param
    "/#{year}/#{month}/#{slug}"
  end
end
(假设您在
Post
类中有
year
month
slug
的方法)

现在,当生成URL时,将调用覆盖到_param的

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

但是,如果覆盖了
to_参数
,默认的RESTful
post_路径
对于您想要生成的url将很好地工作。

如何修复
PostsController
url_?可能不是很优雅,但它是干的,事情应该只是工作

# 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
#app/controllers/posts_controller.rb
类PostsController<应用程序控制器
受保护的
def url_用于(选项={})
如果选项[:年].class.to_==“发布”
obj=选项[:年]
选项[:年]=对象年
选项[:月]=对象月
选项[:slug]=对象slug
结束
超级(选项)
结束
结束

我在试用TempoDB,并用下面的代码扩展了他们的类,这对我很有用。我有“资源:系列”的路线,然后可以毫无问题地使用url_

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

@post对象有:slug字段吗?当然有。我也定义了
.year
.month
方法。我甚至可以使它们成为真正的属性,但这对imo几乎没有帮助。问题在于路由生成。它几乎可以工作。不幸的是,它有一个严重的问题。在Rails3中,生成的链接是url_编码的。所以链接是这样生成的:
url\u for(@post)=>”http://localhost:3000/posts/%2F2010%2F02%2Ffirst“
这不是我想要的。顺便说一句:你的
to_param
方法应该省略第一个
/
。啊,糟糕透了。嗯,
to_param
是实现像这样的自定义路径的常用方法,但我想斜杠已经把它抛到一边了。一个返回所需路径的helper方法怎么样?然后您可以这样做:
。不是很干净,但它会工作。我现在做的方式实际上与您的解决方案类似。我有一个自定义路径方法:
def path;“/{year}/{month}/{slug}”;结束
,我这样使用它:
,它可以工作。但不幸的是@post变量在这种情况下不是一个资源,所以我不能使用RESTful路由后面的所有其他神奇的东西。你觉得你错过了什么神奇的东西?基于您在问题中的代码,您可以对所有内容使用RESTful路由,但show URL…
atom\u提要
要求您传递@post变量(在
feed\u条目(@post)
)中,它应该很好地响应(@post)
URL\u。我假设Rails 3添加了
respond\u with(@user)
也不起作用。这就是我的想法。这只是RESTful路由的一个限制。在Post模型上定义
路由\u散列
没有帮助。Rails路由没有使用它。我知道我可以这样使用它:
,但我希望能够将
url\u用于(@Post)
method.Works!非常非常聪明。当然这只是一个破解,但到目前为止一切都按照预期进行。在Rails 2.3.5和3.0.0中。我印象深刻。顺便说一句:我已经将
url\u移动到了
应用程序控制器
,因为我不仅在
Posts
控制器中使用了
Post
模型,而且在
 站点
controller.Cool hack。您还可以将第一行简化为
options[:year]。class==Post
class TempoDB::Series
  def self.model_name
    ActiveModel::Name.new(TempoDB::Series,nil,'series')
  end
  def to_param
    self.key
  end
end