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_参数
,默认的RESTfulpost_路径
对于您想要生成的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