Ruby on Rails:如何覆盖资源的“show”路由?
目前我的路线看起来像这样:
resources :posts
我想覆盖’show’动作,以便我可以显示如下的URL:
posts/:id/:slug
我目前能够通过添加自定义match
路由来完成此操作:
resources :posts match 'posts/:id/:slug' => 'posts#show'
但是,当我使用link_to
帮助程序时,它不使用我的自定义show route。
# renders /posts/123
如何定义我的show route以便仍然可以使用link_to
helper?
更新:正如您可以阅读以下答案,您可以覆盖“显示”操作的路线,但它可能比它的价值更多的工作。 创建自定义路线更容易:
# config/routes.rb match 'posts/:id/:slug' => 'posts#show', as: 'post_seo' # app/views/posts/index.html.erb
您有两条路线指向posts#show
(您应该能够通过运行rake routes
来确认这一点),并且您的链接使用了错误的rake routes
。
当你调用link_to('show', post)
时,链接的URL是通过调用url_for(post)
生成的(最后,在路上经过其他几个方法之后)调用post_path(post)
。 由于您通过调用resources(:posts)
创建的resources(:posts)
post_path
的路由命名为post
,这是post_path
生成的路由。
您目前还有不一致的路由,用于显示,更新和销毁操作,这些操作可能会在以后引起您的问题。
您可以通过将路由更改为以下内容来解决此问题:
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
作为构建post路径所需的单个参数。 您的自定义路由需要两个参数,一个id
和一个slug
。 所以现在您的链接代码需要如下所示:
link_to 'show', post_path(post.id, post.slug)
您可以通过在app/helpers/posts_helper.rb
定义自己的post_path
和post_url
帮助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
这意味着我们终于可以使用:
link_to 'show', post
如果这一切看起来都太多了,那么常见的替代方法是使用看起来更像posts/:id-:slug
URL,在这种情况下,您可以坚持使用标准的RESTful路由,并在Post
类中覆盖to_param
方法:
def to_param "#{id}-#{slug}" end
你还需要做一些工作,将params[:id]
分成ID和slug,然后才能在你的show中查找相关实例,编辑,更新和破坏控制器动作。
resources :posts, except: :show do get ":slug" => :show, as: "", on: :member end
并定义帮助器
def post_path post "/posts/#{post.id}/#{post.slug}" end
分贝/迁移/ add_slug_to_articles.rb
add_column :articles, :slug, :string add_index :articles, :slug
车型/ article.rb
class Article < ActiveRecord::Base extend FriendlyId friendly_id :name, use: :slugged def should_generate_new_friendly_id? new_record? end end
要么...
class Article < ActiveRecord::Base extend FriendlyId friendly_id :name, use: :history end
http://railscasts.com/episodes/314-pretty-urls-with-friendlyid