754ed1f45b
https://github.com/rails/rails/pull/39935 changed the behavior of `Path::Pattern#spec` and `Route#ast` to return an `Ast` rather than the root `Node`. After eager loading, however, we clear out the `Ast` to limit retained memory and these methods return `nil`. While these methods are not public and they aren't used internally after eager loading, having them return `nil` makes it difficult for applications that had been using these methods to get access to the root `Node`. This commit restores the behavior of these two methods to return the root `Node`. The `Ast` is still available via `Path::Pattern#ast`, and we still clear it out after eager loading. Now that spec is a `Node` and not an `Ast` masquerading as one, we can get rid of the delegate methods on `Ast. Since `Route#ast` now returns the root `Node`, the newly added `Route#ast_root` is no longer necessary so I've removed it. I also removed the unused `@decorated_ast` method, which should have been removed in https://github.com/rails/rails/pull/39935.
81 lines
1.7 KiB
Ruby
81 lines
1.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module ActionDispatch
|
|
module Journey # :nodoc:
|
|
# The Routing table. Contains all routes for a system. Routes can be
|
|
# added to the table by calling Routes#add_route.
|
|
class Routes # :nodoc:
|
|
include Enumerable
|
|
|
|
attr_reader :routes, :custom_routes, :anchored_routes
|
|
|
|
def initialize
|
|
@routes = []
|
|
@ast = nil
|
|
@anchored_routes = []
|
|
@custom_routes = []
|
|
@simulator = nil
|
|
end
|
|
|
|
def empty?
|
|
routes.empty?
|
|
end
|
|
|
|
def length
|
|
routes.length
|
|
end
|
|
alias :size :length
|
|
|
|
def last
|
|
routes.last
|
|
end
|
|
|
|
def each(&block)
|
|
routes.each(&block)
|
|
end
|
|
|
|
def clear
|
|
routes.clear
|
|
anchored_routes.clear
|
|
custom_routes.clear
|
|
end
|
|
|
|
def partition_route(route)
|
|
if route.path.anchored && route.path.requirements_anchored?
|
|
anchored_routes << route
|
|
else
|
|
custom_routes << route
|
|
end
|
|
end
|
|
|
|
def ast
|
|
@ast ||= begin
|
|
nodes = anchored_routes.map(&:ast)
|
|
Nodes::Or.new(nodes)
|
|
end
|
|
end
|
|
|
|
def simulator
|
|
@simulator ||= begin
|
|
gtg = GTG::Builder.new(ast).transition_table
|
|
GTG::Simulator.new(gtg)
|
|
end
|
|
end
|
|
|
|
def add_route(name, mapping)
|
|
route = mapping.make_route name, routes.length
|
|
routes << route
|
|
partition_route(route)
|
|
clear_cache!
|
|
route
|
|
end
|
|
|
|
private
|
|
def clear_cache!
|
|
@ast = nil
|
|
@simulator = nil
|
|
end
|
|
end
|
|
end
|
|
end
|