Ruby on rails 试图理解旅程::路径::模式#规范(轨道路由的内部)
上下文:我正在解决一个需要外部审计程序才能理解和“应用”Rails路由的问题。编写此外部程序的一个选项是解析Ruby on rails 试图理解旅程::路径::模式#规范(轨道路由的内部),ruby-on-rails,routes,internals,journey,Ruby On Rails,Routes,Internals,Journey,上下文:我正在解决一个需要外部审计程序才能理解和“应用”Rails路由的问题。编写此外部程序的一个选项是解析rake路由的输出,但这将不必要地导致复制解析这些路由并将其转换为结构良好的travel::Route对象的代码 因此,我的计划是将Rails.application.routes输出为一种公共格式(YAML或JSON),外部程序可以理解该格式,并可以基于该数据构建路由器 问题:鉴于此上下文,我试图理解旅程::路径::Paternet#spec属性的结构,该属性出现在旅程::路线对象中,恰
rake路由的输出
,但这将不必要地导致复制解析这些路由并将其转换为结构良好的travel::Route
对象的代码
因此,我的计划是将Rails.application.routes
输出为一种公共格式(YAML或JSON),外部程序可以理解该格式,并可以基于该数据构建路由器
问题:鉴于此上下文,我试图理解旅程::路径::Paternet#spec
属性的结构,该属性出现在旅程::路线
对象中,恰好是所有操作的中心
例如,以下路由-/posts/:id
-转换为以下“spec”——
#
对象中的左/右属性是什么?什么决定了哪个令牌是“左”令牌和哪个令牌是“右”旅程::节点::Cat
- 这看起来很像二叉树,但为什么第一个标记(即第一个
)是“最里面的”(或叶节点)?它不应该是“最外层”(或根节点)吗/
- 在执行路由匹配时,沿着此数据结构走下去的有效方法是什么
travel::Nodes::Cat
只是您可能遇到的节点类型之一,它是匹配路径中表达式
规则的二进制节点,左侧是第一个表达式
,右侧
是所有其他节点,这将生成使用所有表达式的循环
关于外部路由分析的其他想法:在一般情况下,路由不能转储到静态文件中,因为它们可以包含:
- 具有非纯函数的动态约束(例如-
,其思想是结果可以依赖于请求、时间或状态等之外的内容)当这些存在时,即使rails路由器本身也可以在对同一请求进行第二次运行时产生不同的结果get:r,约束:->{rand(2)>0}
- 安装的机架应用程序-可以具有硬编码或非rails路由器
- rails引擎——有rails路由器,比一般的机架式应用程序更容易,但有安装点和合并到主应用程序范围的技巧
ActionDispatch::Routing::RouteInspector
,它用于rake routes
,并获得结构化路由信息,这比只解析后一个输出更好
在gemroutes\u coverage
中,我这样做:
class Inspector < ActionDispatch::Routing::RoutesInspector
def collect_all_routes
res = collect_routes(@routes)
@engines.each do |engine_name, engine_routes|
res += engine_routes.map{|er|
er.merge({ engine_name: engine_name })
}
end
res
end
def collect_routes(routes)
routes.collect do |route|
ActionDispatch::Routing::RouteWrapper.new(route)
end.reject do |route|
route.internal?
end.collect do |route|
collect_engine_routes(route)
{ name: route.name,
verb: route.verb,
path: route.path,
reqs: route.reqs,
original: route,
}
end
end
res = Inspector.new(Rails.application.routes.routes.routes).collect_all_routes
类检查器
旅程基于匹配路线的有限状态机,有内置的可视化工具(需要graphviz):
travel::Nodes::Cat
只是您可能遇到的节点类型之一,它是匹配路径中表达式
规则的二进制节点,左侧是第一个表达式
,右侧
是所有其他节点,这将生成使用所有表达式的循环
关于外部路由分析的其他想法:在一般情况下,路由不能转储到静态文件中,因为它们可以包含:
- 具有非纯函数的动态约束(例如-
,其思想是结果可以依赖于请求、时间或状态等之外的内容)当这些存在时,即使rails路由器本身也可以在对同一请求进行第二次运行时产生不同的结果get:r,约束:->{rand(2)>0}
- 安装的机架应用程序-可以具有硬编码或非rails路由器
- rails引擎——有rails路由器,比一般的机架式应用程序更容易,但有安装点和合并到主应用程序范围的技巧
ActionDispatch::Routing::RouteInspector
,它用于rake routes
,并获得结构化路由信息,这比只解析后一个输出更好
在gemroutes\u coverage
中,我这样做:
class Inspector < ActionDispatch::Routing::RoutesInspector
def collect_all_routes
res = collect_routes(@routes)
@engines.each do |engine_name, engine_routes|
res += engine_routes.map{|er|
er.merge({ engine_name: engine_name })
}
end
res
end
def collect_routes(routes)
routes.collect do |route|
ActionDispatch::Routing::RouteWrapper.new(route)
end.reject do |route|
route.internal?
end.collect do |route|
collect_engine_routes(route)
{ name: route.name,
verb: route.verb,
path: route.path,
reqs: route.reqs,
original: route,
}
end
end
res = Inspector.new(Rails.application.routes.routes.routes).collect_all_routes
类检查器
class Inspector < ActionDispatch::Routing::RoutesInspector
def collect_all_routes
res = collect_routes(@routes)
@engines.each do |engine_name, engine_routes|
res += engine_routes.map{|er|
er.merge({ engine_name: engine_name })
}
end
res
end
def collect_routes(routes)
routes.collect do |route|
ActionDispatch::Routing::RouteWrapper.new(route)
end.reject do |route|
route.internal?
end.collect do |route|
collect_engine_routes(route)
{ name: route.name,
verb: route.verb,
path: route.path,
reqs: route.reqs,
original: route,
}
end
end
res = Inspector.new(Rails.application.routes.routes.routes).collect_all_routes