Ruby on Rails:如何覆盖资源的“显示"路由? [英] Ruby on Rails: How to override the 'show' route of a resource?
问题描述
目前我有一条看起来像这样的路线:
Currently I have a route that looks like this:
resources :posts
我想覆盖显示"操作,以便我可以显示这样的网址:
I want to override the 'show' action so that I can display a url like this:
posts/:id/:slug
我目前可以通过添加自定义 match
路由来做到这一点:
I am currently able to do this by adding a custom match
route:
resources :posts
match 'posts/:id/:slug' => 'posts#show'
但是,当我使用 link_to
帮助程序时,它不使用我的自定义显示路由.
However, when I use the link_to
helper, it does not use my custom show route.
<%= link_to 'show', post %> # renders /posts/123
如何定义我的表演路线,以便我仍然可以使用 link_to
助手?
How can I define my show route so that I can still use the link_to
helper?
更新:正如您在以下答案中所读到的,您可以覆盖显示"操作的路线,但这可能比它的价值更多.创建自定义路由更容易:
Update: As you can read in the following answers, you can override the route to the 'show' action, but it's probably more work than it's worth. It's easier to just create a custom route:
# config/routes.rb
match 'posts/:id/:slug' => 'posts#show', as: 'post_seo'
# app/views/posts/index.html.erb
<%= link_to post.title, post_seo_path(post.id, post.slug) %>
推荐答案
您有两条路由指向 posts#show
(您应该能够通过运行 rake routes
),而您的链接使用了错误的链接.
You have two routes which point to posts#show
(you should be able to confirm this by running rake routes
), and your link is using the wrong one.
当您调用 link_to('show', post)
时,链接的 URL 是通过调用 url_for(post)
生成的,它(最终,在通过其他几个方法)调用 post_path(post)
.由于您对 resources(:posts)
的调用创建的 posts#show
路由名为 post
,因此 posts#show
的路由code>post_path 生成.
When you call link_to('show', post)
the URL of the link is generated by calling url_for(post)
which (eventually, after passing through several other methods on the way) calls post_path(post)
. Since the route to posts#show
that was created by your call to resources(:posts)
is named post
, that is the route that post_path
generates.
您目前还具有不一致的显示、更新和销毁操作路线,这可能会在以后给您带来问题.
You also currently have inconsistent routes for the show, update and destroy actions which will probably cause you problems later on.
您可以通过将路由更改为以下内容来解决此问题:
You can fix this by changing your routes to the following:
resources :posts, :except => ['show', 'update', 'destroy']
get 'posts/:id/:slug' => 'posts#show', :as => 'post'
put 'posts/:id/:slug' => 'posts#update'
delete 'posts/:id/:slug' => 'posts#destroy'
不幸的是,您仍然不能使用 link_to('show', post)
,因为它依赖于能够使用 post.to_param
作为单个参数需要建立一个帖子的路径.您的自定义路由需要两个参数,一个 id
和一个 slug
.所以现在您的链接代码需要如下所示:
Unfortunately you still can't use link_to('show', post)
just yet, because it relies on being able to use post.to_param
as the single argument needed to build a path to a post. Your custom route requires two arguments, an id
and a slug
. So now your link code will need to look like this:
link_to 'show', post_path(post.id, post.slug)
您可以通过在 app/helpers/posts_helper.rb
中定义自己的 post_path
和 post_url
助手来解决这个问题:
You can get around that problem by defining your own post_path
and post_url
helpers in app/helpers/posts_helper.rb
:
module PostsHelper
def post_path(post, options={})
post_url(post, options.merge(:only_path => true))
end
def post_url(post, options={})
url_for(options.merge(:controller => 'posts', :action => 'show',
:id => post.id, :slug => post.slug))
end
end
这意味着我们终于可以使用了:
Which means we're finally able to use:
link_to 'show', post
<小时>
如果这一切看起来工作量太大,一个常见的替代方法是使用看起来更像 posts/:id-:slug
的 URL,在这种情况下,您可以坚持使用标准的 RESTful 路由和只需覆盖 Post
类中的 to_param
方法:
If that all seems like too much work, a common alternative is to use URLs that look more like posts/:id-:slug
, in which case you can stick with the standard RESTful routes and just override the to_param
method in your Post
class:
def to_param
"#{id}-#{slug}"
end
您还需要做一些工作,将 params[:id]
拆分为 ID 和 slug,然后才能在节目中查找相关实例、编辑、更新并销毁控制器操作.
You'll also need to do a little bit of work splitting up params[:id]
into an ID and a slug before you can look up the relevant instance in your show, edit, update and destroy controller actions.
这篇关于Ruby on Rails:如何覆盖资源的“显示"路由?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!