2014-07-02 63 views
4

我有一个看起来像2条通配符路线:当URL有尾随斜线与约束通配符路线,以结束与斜线

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

国家#列出应该被调用。例子:

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

国家#秀应该叫时,它没有结尾的斜线。示例:

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

目前我的约束似乎不工作,因为所有的请求都去国家#列表。

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

+0

这应该有助于http://stackoverflow.com/questions/6186780/trailing-slash-behavior-in-rails-application?rq=1 – Pavan

+0

@Pavan没有真正帮助(不知道是否相同问题,我无法得到它的工作) – Blankman

回答

7

你应该问问自己,这是否是真正实现你所要做的最好的方法。一般网站不关心目录中的尾部斜杠。例如:

www.facebook.com/username 

将带你到作为同一个地方:

www.facebook.com/username/ 

绝大多数的网站,这样的工作,所以你想现在做的是针对Web约定。它肯定会对搜索引擎优化产生影响,如果你关心的话。即使你不这样做,你应该考虑在测试这些路线时你将面临的困难。你的测试会很脆弱,从长远来看,这会造成很多挫折。

我的建议是:如果你想区分listshow,把它们放到URL中。例如:

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

可以将用户引导至country#list,以“加州”和“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

问题在于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"]是强制性的,但删除了尾随/,所以在这里没有用。

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

+0

好点,我也担心。我支持动态层次结构,因此无法知道URL的哪个部分是类别,哪个是文件名。 – Blankman

+0

在这种情况下,我可能会做类似于@ ege-ersoz建议的内容,并在列表路径的末尾保留一个字符串。 另一种方法是有2阶段路由过程。在路线中,将所有内容路由到单个控制器操作。这个动作可以作为第二级路由器 - 它可以进行必要的查找以确定它是一个列表还是一个show动作,然后相应地发送到控制器上的另一个方法。 – AlexT