rails/actionpack/lib/action_dispatch/journey/routes.rb
Daniel Colson 754ed1f45b
Restore the behavior of journey root node methods
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.
2021-08-12 09:51:38 -04:00

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