我希望我的网站具有如下所示的网址:
example.com/2010/02/my-first-post
我的 Post
模型带有 slug
字段('my-first-post')和 published_on< /code> 字段(我们将从中扣除 url 中的年份和月份部分)。
我希望我的 Post
模型是 RESTful,因此像 url_for(@post)
这样的东西应该像它们应该的那样工作,即:它应该生成上述 url。
有办法做到这一点吗?我知道您需要覆盖 to_param
并设置 map.resources :posts
和 :requirements
选项,但我无法让它全部工作。
我已经快完成了,已经完成了 90%。使用 resource_hacks 插件 我可以实现这一点:
map.resources :posts, :member_path => '/:year/:month/:slug',
:member_path_requirements => {:year => /[\d]{4}/, :month => /[\d]{2}/, :slug => /[a-z0-9\-]+/}
rake routes
(...)
post GET /:year/:month/:slug(.:format) {:controller=>"posts", :action=>"show"}
并在视图中:
<%= link_to 'post', post_path(:slug => @post.slug, :year => '2010', :month => '02') %>
生成正确的 示例.com/2010/02/my-first-post
链接。
我也希望这个能工作:
<%= link_to 'post', post_path(@post) %>
但它需要重写模型中的 to_param 方法。应该相当容易,除了事实上, to_param
必须返回 String
,而不是我想要的 Hash
。
class Post < ActiveRecord::Base
def to_param
{:slug => 'my-first-post', :year => '2010', :month => '02'}
end
end
结果出现can't conversion Hash into String
错误。
这似乎被忽略:
def to_param
'2010/02/my-first-post'
end
因为它导致错误:post_url failed to generated from {:action=>"show", :year=># (它错误地将 @post 对象分配给 :year 键)。我对如何破解它有点一无所知。
I'd like my website to have URLs looking like this:
example.com/2010/02/my-first-post
I have my Post
model with slug
field ('my-first-post') and published_on
field (from which we will deduct the year and month parts in the url).
I want my Post
model to be RESTful, so things like url_for(@post)
work like they should, ie: it should generate the aforementioned url.
Is there a way to do this? I know you need to override to_param
and have map.resources :posts
with :requirements
option set, but I cannot get it all to work.
I have it almost done, I'm 90% there. Using resource_hacks plugin I can achieve this:
map.resources :posts, :member_path => '/:year/:month/:slug',
:member_path_requirements => {:year => /[\d]{4}/, :month => /[\d]{2}/, :slug => /[a-z0-9\-]+/}
rake routes
(...)
post GET /:year/:month/:slug(.:format) {:controller=>"posts", :action=>"show"}
and in the view:
<%= link_to 'post', post_path(:slug => @post.slug, :year => '2010', :month => '02') %>
generates proper example.com/2010/02/my-first-post
link.
I would like this to work too:
<%= link_to 'post', post_path(@post) %>
But it needs overriding the to_param
method in the model. Should be fairly easy, except for the fact, that to_param
must return String
, not Hash
as I'd like it.
class Post < ActiveRecord::Base
def to_param
{:slug => 'my-first-post', :year => '2010', :month => '02'}
end
end
Results in can't convert Hash into String
error.
This seems to be ignored:
def to_param
'2010/02/my-first-post'
end
as it results in error: post_url failed to generate from {:action=>"show", :year=>#<Post id: 1, title: (...)
(it wrongly assigns @post object to the :year key). I'm kind of clueless at how to hack it.
发布评论
评论(5)
Rails 3.x 和 Rails 2.x 的漂亮 URL,无需任何外部插件,但不幸的是,有一些 hack。
paths.rb
application_controller.rb
post.rb
view
注意,对于 Rails 3.x,您可能想要使用此路由定义:
是否有任何徽章可以回答您自己的问题? ;)
顺便说一句: routing_test 文件是一个了解 Rails 路由功能的好地方。
更新:使用
default_url_options
是一个死胡同。仅当控制器中定义了@post
变量时,发布的解决方案才有效。例如,如果存在带有帖子数组的@posts
变量,那么我们就不走运了(因为default_url_options
无权访问视图变量,例如p
in@posts.each do |p|
所以这仍然是一个悬而未决的问题有人帮忙吗?
Pretty URLs for Rails 3.x and Rails 2.x without the need for any external plugin, but with a little hack, unfortunately.
routes.rb
application_controller.rb
post.rb
view
Note, for Rails 3.x you might want to use this route definition:
Is there any badge for answering your own question? ;)
Btw: the routing_test file is a good place to see what you can do with Rails routing.
Update: Using
default_url_options
is a dead end. The posted solution works only when there is@post
variable defined in the controller. If there is, for example,@posts
variable with Array of posts, we are out of luck (becasedefault_url_options
doesn't have access to view variables, likep
in@posts.each do |p|
.So this is still an open problem. Somebody help?
它仍然是一个黑客,但以下内容有效:
在
application_controller.rb
中:以下内容将有效(在 Rails 2.3.x 和 3.0.0 中):
这是一些 善良的灵魂对于我的类似问题,自定义 RESTful 资源的 url_for(复合键;不仅仅是 id)。
It's still a hack, but the following works:
In
application_controller.rb
:And the following will work (both in Rails 2.3.x and 3.0.0):
This is the answer from some nice soul for a similar question of mine, url_for of a custom RESTful resource (composite key; not just id).
Ryan Bates 在他的截屏中谈到了“如何添加自定义路由、使某些参数可选以及添加其他参数的要求”。
http://railscasts.com/episodes/70-custom-routes
Ryan Bates talked about it in his screen cast "how to add custom routes, make some parameters optional, and add requirements for other parameters."
http://railscasts.com/episodes/70-custom-routes
这可能会有所帮助。您可以在中定义
default_url_options
方法您的ApplicationController
接收传递给 url 帮助器的选项哈希,并返回您想要用于这些 url 的其他选项的哈希。如果将帖子作为
post_path
的参数给出,它将被分配给路线的第一个(未分配的)参数。还没有测试过,但它可能会起作用:我处于类似的情况,其中帖子有语言参数和 slug 参数。写入
post_path(@post)
会将此哈希值发送到default_url_options
方法:更新:存在一个问题,您无法覆盖该方法中的 url 参数。传递给 url 帮助器的参数优先。因此,您可以执行以下操作:
and:
如果
Post.to_param
返回 slug,则这将起作用。您只需将年份和月份添加到哈希中即可。This might be helpful. You can define a
default_url_options
method in yourApplicationController
that receives a Hash of options that were passed to the url helper and returns a Hash of additional options that you want to use for those urls.If a post is given as a parameter to
post_path
, it will be assigned to the first (unnassigned) parameter of the route. Haven't tested it, but it might work:I'm in the similar situation, where a post has a language parameter and slug parameter. Writing
post_path(@post)
sends this hash to thedefault_url_options
method:UPDATE: There's a problem that you can't override url parameters from that method. The parameters passed to the url helper take precedence. So you could do something like:
and:
This would work if
Post.to_param
returned the slug. You would only need to add the year and month to the hash.您可以使用 friend_id 来减轻自己的压力。它太棒了,可以完成工作,您可以观看 Ryan 的截屏视频贝茨开始吧。
You could just save yourself the stress and use friendly_id. Its awesome, does the job and you could look at a screencast by Ryan Bates to get started.