如果slug不正确,则Rails路由重定向

时间:2016-12-29 17:36:47

标签: ruby-on-rails

在我的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来完成吗?或者我必须做一些自定义的事情吗?

2 个答案:

答案 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进行搜索引擎优化。