具有约束的通配符路由以尾部斜杠结束

我有2个通配符路由,如下所示:

get '*country_path/', to: 'country#list', constraints: { country_path: /\/$/ } get '*country_path/:title', to: 'country#show' 

当url有一个尾部斜杠时,应该调用country #list。 例子:

 www.example.com/usa/california/ www.example.com/usa/california/abc/ 

country#show应该在没有尾部斜杠时调用。 例子:

 www.example.com/usa/californa/travel www.example.com/usa/californa/average-income 

目前我的约束似乎不起作用,因为所有请求都转到country #list。

我的路线约束有什么问题?

您应该问问自己这是否真的是实现您想要做的事情的最佳方式。 网站通常不关心目录中的尾部斜杠。 例如:

 www.facebook.com/username 

会带你到同一个地方:

 www.facebook.com/username/ 

绝大多数网站都是这样工作的,所以你现在要做的就是反对网络惯例。 如果你关心它,肯定会对SEO产生影响。 即使你不这样做,也应该考虑在测试这些路线时你将面临的困难。 你的测试会很脆弱,从长远来看这会带来很大的挫败感。

我的建议如下:如果你想区分listshow ,请将它们放入URL中。 例如:

 www.example.com/usa/california/list www.example.com/usa/california/abc/list 

可以将用户带到country#list ,以“california”和“abc”作为参数。 同理:

 www.example.com/usa/californa/travel/show www.example.com/usa/californa/average-income/show 

可以将用户带到country#show 。 这要容易得多。 它也更标准和用户友好。 有关更多信息,请参阅外部的Rails路由。

麻烦的是Rails在它到达路由之前已经删除尾随/因此使用传统方法无法匹配它。 唯一的方法是使用高级约束 。 以下内容适合您的需求:

 # config/routes.rb class TrailingSlashMatcher def matches?(request) uri = request.env["REQUEST_URI"] uri.present? && uri.end_with?("/") end end Rails.application.routes.draw do get '*country_path', to: 'country#list', :constraints => TrailingSlashMatcher.new get '*country_path/:title', to: 'country#show' end 

(摘自这里 )。

这种方法的问题在于它不适用于所有情况。 它适用于对服务器的实际请求,但在从测试等调用时可能会出现问题。原因是REQUEST_URI env变量不是机架规范的一部分,因此不是由测试框架设置的。 env["PATH_INFO"]是必需的,但是有尾随/删除,所以这里不好。

总而言之,重新考虑您的路线设计可能是值得的。 匹配是否存在尾随/相当脆弱。 它还可能导致您的用户感到困惑(例如,链接被复制/粘贴等)。 没有其他方法可以区分列表和显示请求(可能基于路径的深度)。