试图了解Journey :: Path :: Pattern#spec(Rails路由的内部)

时间:2019-04-03 04:50:22

标签: ruby-on-rails routes internals journey

上下文:我正在解决一个需要外部审核程序才能理解和“应用” Rails路线的问题。编写此外部程序的一种选择可能是解析rake routes的输出,但这将不必要地最终复制解析这些路由并将其转换为结构良好的Journey::Route对象的代码。

因此,我的计划是将Rails.application.routes输出为外部程序可以理解的通用格式(YAML或JSON),并可以基于此数据构建路由器。

问题:在这种情况下,我试图了解Journey::Path::Paternet#spec属性的结构,该属性出现在Journey::Route对象内部,并且恰好是中心所有动作。

例如,以下路由-/posts/:id-转换为以下“ spec”-

 #<Journey::Nodes::Cat:0x00007ff193327ee0
 @left=
  #<Journey::Nodes::Cat:0x00007ff193308630
   @left=
    #<Journey::Nodes::Cat:0x00007ff1933087e8
     @left=
      #<Journey::Nodes::Cat:0x00007ff193308bf8
       @left=#<Journey::Nodes::Slash:0x00007ff193308d38 @left="/", @memo=nil>,
       @memo=nil,
       @right=#<Journey::Nodes::Literal:0x00007ff193308c48 @left="posts", @memo=nil>>,
     @memo=nil,
     @right=#<Journey::Nodes::Slash:0x00007ff193308a40 @left="/", @memo=nil>>,
   @memo=nil,
   @right=#<Journey::Nodes::Symbol:0x00007ff1933086d0 @left=":id", @memo=nil, @regexp=/[^\.\/\?]+/>>,
 @memo=nil,
 @right=
  #<Journey::Nodes::Group:0x00007ff193309c10
   @left=
    #<Journey::Nodes::Cat:0x00007ff193308220
     @left=#<Journey::Nodes::Dot:0x00007ff1933084f0 @left=".", @memo=nil>,
     @memo=nil,
     @right=#<Journey::Nodes::Symbol:0x00007ff193308338 @left=":format", @memo=nil, @regexp=/[^\.\/\?]+/>>,
   @memo=nil>>
  • Journey::Nodes::Cat对象中的left / right属性是什么?什么决定哪个令牌将是“左”,哪个令牌将是“右”
  • 这看起来像一棵二叉树,但是为什么第一个令牌(即第一个/),“最内层”(或叶节点)呢?应该不是“最外层”(或根节点)吗?
  • 执行路线匹配时,有什么有效的方法可以沿这种数据结构走下去?

1 个答案:

答案 0 :(得分:0)

旅程基于匹配路线的有限状态机,有内置的可视化工具(需要graphviz):

File.open('routes.html', 'wt'){|f| f.write Rails.application.routes.router.visualizer }

Journey::Nodes::Cat只是您可以遇到的节点类型之一,它是与路径grammar, see parser.y中的expressions规则匹配的二进制节点,左边是第一个expression,{{ 1}}就是其他所有,这会产生一个使用所有表达式的循环。

关于外部路由分析的其他想法:在一般情况下,路由不能转储到静态文件中,因为它们可能包含:

  • 具有非纯函数的动态约束(例如-right,想法是结果可能取决于请求,时间或状态等之外的其他因素)(如果存在)-即使是Rails路由器本身可以在同一请求的第二次运行中产生不同的结果。

  • 已安装的机架应用程序-可以具有硬编码或无轨路由器

  • rails引擎-具有rails路由器,比普通的机架应用程序更容易,但是带有挂载点并合并到主应用程序范围的诡计

但在简单的情况下,您可以使用get :r, constraints: ->{rand(2)>0}所用的rails的ActionDispatch::Routing::RoutesInspector并获取结构化路线信息,该信息比仅解析后者的输出要好。

在宝石rake routes中,我这样做:

routes_coverage