Class: ActionDispatch::Routing::RouteSet
| Relationships & Source Files | |
| Namespace Children | |
|
Modules:
| |
|
Classes:
| |
| Extension / Inclusion / Inheritance Descendants | |
|
Subclasses:
|
|
| Inherits: | Object |
| Defined in: | actionpack/lib/action_dispatch/routing/route_set.rb |
Overview
The RouteSet contains a collection of Route instances, representing the routes
typically defined in config/routes.rb.
Constant Summary
-
DEFAULT_CONFIG =
Internal use only
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 432Config.new(nil, false, nil)
-
PATH =
Internal use only
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 397
strategy for building URLs to send to the client
ActiveSupport::Ractors.shareable_lambda { || ActionDispatch::Http::URL.path_for() }
-
RESERVED_OPTIONS =
Internal use only
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 899[:host, :protocol, :port, :subdomain, :domain, :tld_length, :trailing_slash, :anchor, :params, :only_path, :script_name, :original_script_name].freeze
-
UNKNOWN =
Internal use only
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 398ActiveSupport::Ractors.shareable_lambda { || ActionDispatch::Http::URL.url_for() }
Class Method Summary
- .default_resources_path_names Internal use only
- .new(config = DEFAULT_CONFIG.dup) ⇒ RouteSet constructor Internal use only
- .new_with_config(config) Internal use only
Instance Attribute Summary
- #api_only? ⇒ Boolean readonly Internal use only
- #default_scope rw Internal use only
- #default_scope=(new_default_scope) rw Internal use only
- #default_url_options rw Internal use only
- #disable_clear_and_finalize rw Internal use only
- #draw_paths rw Internal use only
- #empty? ⇒ Boolean readonly Internal use only
- #env_key readonly Internal use only
- #formatter rw Internal use only
- #named_routes rw Internal use only
- #optimize_routes_generation? ⇒ Boolean readonly Internal use only
- #polymorphic_mappings readonly Internal use only
- #resources_path_names rw Internal use only
- #router rw Internal use only
-
#routes
readonly
Internal use only
Alias for #set.
- #set (also: #routes) rw Internal use only
Instance Method Summary
-
#from_requirements(requirements)
Returns a Route matching the given requirements, or
nilif none are found. - #add_polymorphic_mapping(klass, options, &block) Internal use only
- #add_route(mapping, name) Internal use only
- #add_url_helper(name, options, &block) Internal use only
- #append(&block) Internal use only
- #call(env) Internal use only
- #clear! Internal use only
- #default_env Internal use only
- #define_mounted_helper(name, script_namer = nil) Internal use only
- #draw(&block) Internal use only
- #eager_load! Internal use only
-
#extra_keys(options, recall = {})
Internal use only
Generate the path indicated by the arguments, and return an array of the keys that were not used to generate it.
- #finalize! Internal use only
- #find_script_name(options) Internal use only
- #generate_extras(options, recall = {}) Internal use only
- #generate_url_helpers(supports_path) Internal use only
-
#inspect
Internal use only
Since the router holds references to many parts of the system like engines, controllers and the application itself, inspecting the route set can actually be really slow, therefore we default alias inspect to to_s.
-
#missing_controller_messages
Internal use only
Resolves the controller of every route that dispatches to one and returns a message for each route whose controller is missing, so that a broken route can be reported when the routes are loaded rather than on the first request that matches it.
-
#mounted_helpers
Internal use only
Contains all the mounted helpers across different engines and the
main_apphelper for the application. - #path_for(options, route_name = nil, reserved = RESERVED_OPTIONS) Internal use only
- #prepend(&block) Internal use only
- #recognize_path(path, environment = {}) Internal use only
- #recognize_path_with_request(req, path, extras, raise_on_missing: true) Internal use only
- #relative_url_root Internal use only
- #request_class Internal use only
-
#url_for(options, route_name = nil, url_strategy = UNKNOWN, method_name = nil, reserved = RESERVED_OPTIONS)
Internal use only
The
optionsargument must be a hash whose keys are symbols. - #url_helpers(supports_path = true) Internal use only
- #eval_block(block) private Internal use only
- #generate(route_name, options, recall = {}) private Internal use only
- #make_request(env) private Internal use only
Constructor Details
.new(config = DEFAULT_CONFIG.dup) ⇒ RouteSet
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 434
def initialize(config = DEFAULT_CONFIG.dup) self.named_routes = NamedRouteCollection.new self.resources_path_names = self.class.default_resources_path_names self. = {} self.draw_paths = [] @config = config @append = [] @prepend = [] @disable_clear_and_finalize = false @finalized = false @env_key = "ROUTES_#{object_id}_SCRIPT_NAME" @default_env = nil @set = Journey::Routes.new @router = Journey::Router.new @set @formatter = Journey::Formatter.new self @polymorphic_mappings = {} end
Class Method Details
.default_resources_path_names
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 407
def self.default_resources_path_names { new: "new", edit: "edit" } end
.new_with_config(config)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 411
def self.new_with_config(config) route_set_config = DEFAULT_CONFIG.dup # engines apparently don't have this set if config.respond_to? :relative_url_root route_set_config.relative_url_root = config.relative_url_root end if config.respond_to? :api_only route_set_config.api_only = config.api_only end if config.respond_to? :default_scope route_set_config.default_scope = config.default_scope end new route_set_config end
Instance Attribute Details
#api_only? ⇒ Boolean (readonly)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 487
def api_only? @config.api_only end
#default_scope (rw)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 491
def default_scope @config.default_scope end
#default_scope=(new_default_scope) (rw)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 495
def default_scope=(new_default_scope) @config.default_scope = new_default_scope end
#default_url_options (rw)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 402
attr_accessor :, :draw_paths
#disable_clear_and_finalize (rw)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 401
attr_accessor :disable_clear_and_finalize, :resources_path_names
#draw_paths (rw)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 402
attr_accessor :, :draw_paths
#empty? ⇒ Boolean (readonly)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 714
def empty? routes.empty? end
#env_key (readonly)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 403
attr_reader :env_key, :polymorphic_mappings
#formatter (rw)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 400
attr_accessor :formatter, :set, :named_routes, :router
#named_routes (rw)
#optimize_routes_generation? ⇒ Boolean (readonly)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 903
def optimize_routes_generation? .empty? end
#polymorphic_mappings (readonly)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 403
attr_reader :env_key, :polymorphic_mappings
#resources_path_names (rw)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 401
attr_accessor :disable_clear_and_finalize, :resources_path_names
#router (rw)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 400
attr_accessor :formatter, :set, :named_routes, :router
#routes (readonly)
Alias for #set.
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 405
alias :routes :set
#set (rw) Also known as: #routes
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 400
attr_accessor :formatter, :set, :named_routes, :router
Instance Method Details
#add_polymorphic_mapping(klass, options, &block)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 735
def add_polymorphic_mapping(klass, , &block) @polymorphic_mappings[klass] = CustomUrlHelper.new(klass, , &block) end
#add_route(mapping, name)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 718
def add_route(mapping, name) raise ArgumentError, "Invalid route name: '#{name}'" unless name.blank? || name.to_s.match(/^[_a-z]\w*$/i) if name && named_routes[name] raise ArgumentError, "Invalid route name, already in use: '#{name}' \n" \ "You may have defined two routes with the same name using the `:as` option, or " \ "you may be overriding a route already defined by a resource with the same naming. " \ "For the latter, you can restrict the routes created with `resources` as explained here: \n" \ "https://guides.rubyonrails.org/routing.html#restricting-the-routes-created" end route = @set.add_route(name, mapping) named_routes[name] = route if name route end
#add_url_helper(name, options, &block)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 739
def add_url_helper(name, , &block) named_routes.add_url_helper(name, , &block) end
#append(&block)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 534
def append(&block) @append << block end
#call(env)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 955
def call(env) req = make_request(env) path_info = req.path_info unless Journey::Router::Utils.normalized_path?(path_info) req.path_info = Journey::Router::Utils.normalize_path(path_info) end @router.serve(req) end
#clear!
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 563
def clear! @finalized = false named_routes.clear set.clear formatter.clear @polymorphic_mappings.clear @prepend.each { |blk| eval_block(blk) } end
#default_env
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 508
def default_env if != @default_env&.[]("action_dispatch.routes.default_url_options") = .dup.freeze uri = URI(ActionDispatch::Http::URL.full_url_for(host: "example.org", **)) @default_env = { "action_dispatch.routes" => self, "action_dispatch.routes.default_url_options" => , "HTTPS" => uri.scheme == "https" ? "on" : "off", "rack.url_scheme" => uri.scheme, "HTTP_HOST" => uri.port == uri.default_port ? uri.host : "#{uri.host}:#{uri.port}", "SCRIPT_NAME" => uri.path.chomp("/"), "rack.input" => "", }.freeze end @default_env end
#define_mounted_helper(name, script_namer = nil)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 584
def define_mounted_helper(name, script_namer = nil) return if MountedHelpers.method_defined?(name) routes = self helpers = routes.url_helpers MountedHelpers.class_eval do define_method "_#{name}" do RoutesProxy.new(routes, _routes_context, helpers, script_namer) end end MountedHelpers.class_eval(<<-RUBY, __FILE__, __LINE__ + 1) def #{name} @_#{name} ||= _#{name} end RUBY end
#draw(&block)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 527
def draw(&block) clear! unless @disable_clear_and_finalize eval_block(block) finalize! unless @disable_clear_and_finalize nil end
#eager_load!
#eval_block(block) (private)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 542
def eval_block(block) mapper = Mapper.new(self) if default_scope mapper.with_default_scope(default_scope, &block) else mapper.instance_exec(&block) end end
#extra_keys(options, recall = {})
Generate the path indicated by the arguments, and return an array of the keys that were not used to generate it.
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 879
def extra_keys(, recall = {}) generate_extras(, recall).last end
#finalize!
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 552
def finalize! return if @finalized @append.each { |blk| eval_block(blk) } url_helpers(true) url_helpers(false) @finalized = true ActiveSupport::Ractors.try_make_shareable(self) end
#find_script_name(options)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 907
def find_script_name() .delete(:script_name) || relative_url_root || "" end
#from_requirements(requirements)
Returns a Route matching the given requirements, or nil if none are found.
This is intended for use by tools such as Language Servers.
Given the routes are defined as:
resources :posts
Then the following will return the Route for the show action:
Rails.application.routes.from_requirements(controller: "posts", action: "show")
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 29
def from_requirements(requirements) routes.find { |route| route.requirements == requirements } end
#generate(route_name, options, recall = {}) (private)
#generate_extras(options, recall = {})
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 883
def generate_extras(, recall = {}) if recall = .merge(_recall: recall) end route_name = .delete :use_route generator = generate(route_name, , recall) path_info = path_for(, route_name, []) [URI(path_info).path, generator.params.except(:_recall).keys] end
#generate_url_helpers(supports_path)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 611
def generate_url_helpers(supports_path) routes = self Module.new do extend ActiveSupport::Concern include UrlFor # Define url_for in the singleton level so one can do: # Rails.application.routes.url_helpers.url_for(args) proxy_class = Class.new do include UrlFor include routes.named_routes.path_helpers_module include routes.named_routes.url_helpers_module attr_reader :_routes def initialize(routes) @_routes = routes end def optimize_routes_generation? @_routes.optimize_routes_generation? end end @_proxy = proxy_class.new(routes).freeze class << self def url_for() @_proxy.url_for() end def full_url_for() @_proxy.full_url_for() end def route_for(name, *args) @_proxy.route_for(name, *args) end def optimize_routes_generation? @_proxy.optimize_routes_generation? end def polymorphic_url(record_or_hash_or_array, = {}) @_proxy.polymorphic_url(record_or_hash_or_array, ) end def polymorphic_path(record_or_hash_or_array, = {}) @_proxy.polymorphic_path(record_or_hash_or_array, ) end def _routes; @_proxy._routes; end def ; {}; end end url_helpers = routes.named_routes.url_helpers_module # Make named_routes available in the module singleton as well, so one can do: # Rails.application.routes.url_helpers.posts_path extend url_helpers # Any class that includes this module will get all named routes... include url_helpers if supports_path path_helpers = routes.named_routes.path_helpers_module include path_helpers extend path_helpers end helper_module = self # plus a singleton class method called _routes ... included do redefine_singleton_method(:_routes, &ActiveSupport::Ractors.try_shareable_proc { helper_module._routes }) end # And an instance method _routes. Note that UrlFor (included in this module) add # extra conveniences for working with @_routes. define_method(:_routes, ActiveSupport::Ractors.try_shareable_proc { @_routes || helper_module._routes }) define_method(:_generate_paths_by_default, ActiveSupport::Ractors.try_shareable_proc { supports_path }) private :_generate_paths_by_default # If the module is included more than once (for example, in a subclass of an # ancestor that includes the module), ensure that the `_routes` singleton and # instance methods return the desired route set by including a new copy of the # module (recursively if necessary). Note that this method is called for each # inclusion, whereas the above `included` block is run only for the initial # inclusion of each copy. def self.included(base) super if base.respond_to?(:_routes) && !base._routes.equal?(@_proxy._routes) @dup_for_reinclude ||= self.dup base.include @dup_for_reinclude end end end end
#inspect
Since the router holds references to many parts of the system like engines, controllers and the application itself, inspecting the route set can actually be really slow, therefore we default alias inspect to to_s.
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 37
alias inspect to_s
#make_request(env) (private)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 503
def make_request(env) request_class.new env end
#missing_controller_messages
Resolves the controller of every route that dispatches to one and returns a message for each route whose controller is missing, so that a broken route can be reported when the routes are loaded rather than on the first request that matches it.
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 465
def # :nodoc: request = request_class.empty routes.filter_map do |route| next unless route.dispatcher? next if StaticDispatcher === route.app begin request.controller_class_for(route.defaults[:controller]) nil rescue MissingController => error = +"#{route.verb} #{route.path.spec} references a missing controller: #{error.}" << " (defined at #{route.source_location})" if route.source_location end end end
#mounted_helpers
Contains all the mounted helpers across different engines and the main_app
helper for the application. You can include this in your classes if you want
to access routes for other engines.
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 580
def mounted_helpers MountedHelpers end
#path_for(options, route_name = nil, reserved = RESERVED_OPTIONS)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 911
def path_for(, route_name = nil, reserved = RESERVED_OPTIONS) url_for(, route_name, PATH, nil, reserved) end
#prepend(&block)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 538
def prepend(&block) @prepend << block end
#recognize_path(path, environment = {})
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 964
def recognize_path(path, environment = {}) method = (environment[:method] || "GET").to_s.upcase path = Journey::Router::Utils.normalize_path(path) unless path&.include?("://") extras = environment[:extras] || {} begin env = Rack::MockRequest.env_for(path, method: method) rescue URI::InvalidURIError => e raise ActionController::RoutingError, e. end req = make_request(env) recognize_path_with_request(req, path, extras) end
#recognize_path_with_request(req, path, extras, raise_on_missing: true)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 979
def recognize_path_with_request(req, path, extras, raise_on_missing: true) @router.recognize(req) do |route, params| params.merge!(extras) params.each do |key, value| if value.is_a?(String) value = value.dup.force_encoding(Encoding::BINARY) params[key] = URI::RFC2396_PARSER.unescape(value) end end req.path_parameters = params app = route.app if app.matches?(req) && app.dispatcher? begin req.controller_class rescue NameError raise ActionController::RoutingError, "A route matches #{path.inspect}, but references missing controller: #{params[:controller].camelize}Controller" end return req.path_parameters elsif app.matches?(req) && app.engine? path_parameters = app.rack_app.routes.recognize_path_with_request(req, path, extras, raise_on_missing: false) return path_parameters if path_parameters end end if raise_on_missing raise ActionController::RoutingError, "No route matches #{path.inspect}" end end
#relative_url_root
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 483
def relative_url_root @config.relative_url_root end
#request_class
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 499
def request_class ActionDispatch::Request end
#url_for(options, route_name = nil, url_strategy = UNKNOWN, method_name = nil, reserved = RESERVED_OPTIONS)
The options argument must be a hash whose keys are symbols.
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 916
def url_for(, route_name = nil, url_strategy = UNKNOWN, method_name = nil, reserved = RESERVED_OPTIONS) = .merge has_auth = [:user] && [:password] recall = .delete(:_recall) { {} } original_script_name = .delete(:original_script_name) script_name = find_script_name if original_script_name script_name = original_script_name + script_name end = has_auth ? .except(:user, :password, *reserved) : .except(*reserved) route_with_params = generate(route_name, , recall) path = route_with_params.path(method_name) if [:trailing_slash] && ![:format] && !path.end_with?("/") path += "/" end params = route_with_params.params if .key? :params if [:params].respond_to?(:to_hash) params.merge! [:params] else params[:params] = [:params] end end [:path] = path [:script_name] = script_name [:params] = params url_strategy.call end
#url_helpers(supports_path = true)
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 603
def url_helpers(supports_path = true) if supports_path @url_helpers_with_paths ||= generate_url_helpers(true) else @url_helpers_without_paths ||= generate_url_helpers(false) end end