我有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。
我的路线限制有什么问题?
答案 0 :(得分:7)
你应该问问自己这是否真的是完成你想要做的事情的最好方法。网站通常不关心目录中的尾部斜杠。例如:
www.facebook.com/username
将带你到同一个地方:
www.facebook.com/username/
绝大多数网站都是这样工作的,所以你现在要做的就是反对网络惯例。如果你关心它,肯定会对SEO产生影响。即使你不这样做,也应该考虑在测试这些路线时你将面临的困难。你的测试会很脆弱,从长远来看这会引起很多挫折。
我的建议如下:如果您想区分list
和show
,请将这些内容放入网址中。例如:
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 Routing from the Outside In.
答案 1 :(得分:2)
问题是Rails在到达路由之前已经删除了尾随/
,因此使用传统方法无法匹配它。唯一的方法是使用advanced constraint。以下内容适合您的需求:
# 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
(取自here)。
这种方法的问题在于它在所有情况下都不会起作用。它适用于对服务器的实际请求,但在从测试等调用时可能会出现问题。原因是REQUEST_URI
env变量不是rack spec的一部分,因此不受测试框架的限制。 env["PATH_INFO"]
是强制性的,但会删除尾随/
,所以这里不好。
总而言之,重新考虑路线的设计可能是值得的。匹配是否存在尾随/
是相当脆弱的。它还可能导致您的用户感到困惑(例如,链接被复制/粘贴等)。没有其他方法可以区分列表和显示请求(可能基于路径的深度)。