上下文:--我正在解决一个问题,需要一个外部审计程序来理解和“应用”Rails路由。编写这个外部程序的一个选择可能是解析rake routes的输出,但这将不必要地重复解析这些路由并将它们转换为结构良好的Journey::Route对象的代码。
因此,我的计划是将Rails.application.routes输出到公共格式(YAML,或JSON),外部程序可以理解这种格式,并可以基于这些数据构建路由器。
问题:在这个上下文中,我试图理解属性的结构,该属性发生在Journey::Route对象中,恰好是所有操作的中心。
例如,以下路由- /posts/:id -被转换为以下“规范”-
#<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对象中的左/右属性是什么?什么决定哪个标记将“左”,哪个令牌将“右”。/)、“最里面的”(或一个叶节点)?它不应该是“最外面的”(或者根节点)吗?发布于 2019-04-12 11:13:02
旅行是基于与路由匹配的有限状态机,有内置的可视化工具(需要图形):
File.open('routes.html', 'wt'){|f| f.write Rails.application.routes.router.visualizer }Journey::Nodes::Cat只是您可以遇到的节点类型之一,它是在路径语法,见parser.y中匹配expressions规则的二进制节点,左边是first expression,right是所有其他节点,这会产生消耗所有表达式的循环。
关于外部路由分析的其他想法:在一般情况下,路由不能转储到静态文件中,因为它们可以包含:
get :r, constraints: ->{rand(2)>0},思想是结果可以依赖于请求、时间或状态以外的东西,等等)当出现这些情况时,即使是rails路由器本身也可以在第二次运行同一请求时产生不同的结果。但是对于简单的情况,您可以访问rails的ActionDispatch::Routing::RoutesInspector (用于rake routes ),并获得结构化路由信息,这比解析后一个输出更好。
在gem routes_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_routeshttps://stackoverflow.com/questions/55487301
复制相似问题