在我的Rails应用程序中,我有帖子,他们有这样的路线:
match '/posts/:id' => 'posts#show', :via => :get, :as => :post
在我的模特中,我有:
def to_param
"#{id}/#{slug}"
end
这样我就可以拥有一个漂亮的网址:
/posts/1/This-is-a-post
然而,第一个问题我认为/
和id
之间的slug
已被编码!所以我最终得到:/posts/1%2FThis-is-a-post
第二个问题我有,我把它作为slug并不重要,它总是显示帖子。虽然这不错,但这意味着URL完整性会丢失,因为同一帖子可能有很多变化。
我想做的是让它像Stack Overflow一样工作,如果用户点击这些网址中的任何一个
/posts/1
/posts/1/This-is-a
/posts/1/this_is-A-PoSt
/posts/1/sifiusfheud
它会自动重定向到
/posts/1/This-is-a-post
如何在Rails中执行此操作?我可以使用to_param
来完成吗?或者我必须做一些自定义的事情吗?
答案 0 :(得分:1)
这样的路线怎么样?
get '/posts/:id/:slug' => 'posts#show', as: :post_with_slug
然后在像
这样的视图中使用它= link_to 'Post...', post_with_slug_path(:id @post.id, slug: @post.slug)
然后你可以检查控制器中的拼写并找到正确的帖子拼写。
然后还有friendly_id
宝石非常有用。
答案 1 :(得分:0)
这就是我的想法(灵感来自冰人的评论)。
两条路线:
match '/posts/:id' => 'posts#show', :via => :get, :as => :post
match '/posts/:id/:slug' => 'posts#show', :via => :get, :as => :post_with_slug
然后使用post_with_slug
作为链接:
<%= link_to post.title, post_with_slug_path(id: post.id, slug: post.slug) %>
但随后又带着帮手进一步采取行动:
def post_with_slug(post)
"/posts/#{[post.id, post.slug].join('/')}"
end
所以我可以传递对象:
<%= link_to post.title, post_with_slug(post) %>
如果slug param不匹配,最后重定向。
def show
@post = Post.find(params[:id])
redirect_to post_with_slug_path(id: @post.id, slug: @post.slug), :status => 301 if @post.slug != params[:slug]
end
这看起来效果很好,甚至可以处理slug和ID之间的斜线是否缺失或不同,并始终将用户重定向到正确的url。我添加了一个301状态,以防万一用户使用不正确或旧的slufor进行搜索引擎优化。