Class: ActionDispatch::Routing::RouteSet
Relationships & Source Files | |
Namespace Children | |
Modules:
| |
Classes:
| |
Inherits: | Object |
Defined in: | actionpack/lib/action_dispatch/routing/route_set.rb |
Constant Summary
-
DEFAULT_CONFIG =
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 364Config.new(nil, false)
-
PATH =
strategy for building URLs to send to the client
->( ) { ActionDispatch::Http::URL.path_for( ) }
-
RESERVED_OPTIONS =
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 814[:host, :protocol, :port, :subdomain, :domain, :tld_length, :trailing_slash, :anchor, :params, :only_path, :script_name, :original_script_name]
-
UNKNOWN =
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 334->( ) { ActionDispatch::Http::URL.url_for( ) }
Class Method Summary
Instance Attribute Summary
- #api_only? ⇒ Boolean readonly
- #default_scope rw
- #default_url_options rw
- #disable_clear_and_finalize rw
- #draw_paths rw
- #empty? ⇒ Boolean readonly
- #env_key readonly
- #formatter rw
- #named_routes rw
- #optimize_routes_generation? ⇒ Boolean readonly
- #polymorphic_mappings readonly
- #resources_path_names rw
- #router rw
-
#routes
readonly
Alias for #set.
- #set (also: #routes) rw
Instance Method Summary
- #add_polymorphic_mapping(klass, options, &block)
- #add_route(mapping, name)
- #add_url_helper(name, options, &block)
- #append(&block)
- #call(env)
- #clear!
- #default_env
- #define_mounted_helper(name, script_namer = nil)
- #draw(&block)
- #eager_load!
-
#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.
- #finalize!
- #find_script_name(options)
- #generate_extras(options, recall = {})
- #generate_url_helpers(supports_path)
-
#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.
-
#mounted_helpers
Contains all the mounted helpers across different engines and the
main_app
helper for the application. - #path_for(options, route_name = nil, reserved = RESERVED_OPTIONS)
- #prepend(&block)
- #recognize_path(path, environment = {})
- #recognize_path_with_request(req, path, extras, raise_on_missing: true)
- #relative_url_root
- #request_class
-
#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. - #url_helpers(supports_path = true)
- #eval_block(block) private
- #generate(route_name, options, recall = {}, method_name = nil) private
- #make_request(env) private
Constructor Details
.new(config = DEFAULT_CONFIG) ⇒ RouteSet
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 366
def initialize(config = DEFAULT_CONFIG) 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
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 343
def self.default_resources_path_names { new: "new", edit: "edit" } end
.new_with_config(config)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 347
def self.new_with_config(config) route_set_config = DEFAULT_CONFIG # 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 new route_set_config end
Instance Attribute Details
#api_only? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 396
def api_only? @config.api_only end
#default_scope (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 336
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
#default_url_options (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 338
attr_accessor :, :draw_paths
#disable_clear_and_finalize (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 337
attr_accessor :disable_clear_and_finalize, :resources_path_names
#draw_paths (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 338
attr_accessor :, :draw_paths
#empty? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 614
def empty? routes.empty? end
#env_key (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 339
attr_reader :env_key, :polymorphic_mappings
#formatter (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 336
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
#named_routes (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 336
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
#optimize_routes_generation? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 818
def optimize_routes_generation? .empty? end
#polymorphic_mappings (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 339
attr_reader :env_key, :polymorphic_mappings
#resources_path_names (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 337
attr_accessor :disable_clear_and_finalize, :resources_path_names
#router (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 336
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
#routes (readonly)
Alias for #set.
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 341
alias :routes :set
#set (rw) Also known as: #routes
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 336
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
Instance Method Details
#add_polymorphic_mapping(klass, options, &block)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 649
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 618
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 if route.segment_keys.include?(:controller) ActionDispatch.deprecator.warn(<<-MSG.squish) Using a dynamic :controller segment in a route is deprecated and will be removed in Rails 7.2. MSG end if route.segment_keys.include?(:action) ActionDispatch.deprecator.warn(<<-MSG.squish) Using a dynamic :action segment in a route is deprecated and will be removed in Rails 7.2. MSG end route end
#add_url_helper(name, options, &block)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 653
def add_url_helper(name, , &block) named_routes.add_url_helper(name, , &block) end
#append(&block)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 435
def append(&block) @append << block end
#call(env)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 879
def call(env) req = make_request(env) req.path_info = Journey::Router::Utils.normalize_path(req.path_info) @router.serve(req) end
#clear!
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 459
def clear! @finalized = false named_routes.clear set.clear formatter.clear @polymorphic_mappings.clear @prepend.each { |blk| eval_block(blk) } end
#default_env
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 409
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)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 481
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)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 428
def draw(&block) clear! unless @disable_clear_and_finalize eval_block(block) finalize! unless @disable_clear_and_finalize nil end
#eager_load!
[ GitHub ]#eval_block(block) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 443
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 794
def extra_keys(, recall = {}) generate_extras(, recall).last end
#finalize!
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 453
def finalize! return if @finalized @append.each { |blk| eval_block(blk) } @finalized = true end
#find_script_name(options)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 822
def find_script_name( ) .delete(:script_name) || relative_url_root || "" end
#generate(route_name, options, recall = {}, method_name = nil) (private)
[ GitHub ]#generate_extras(options, recall = {})
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 798
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)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 508
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) 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 # plus a singleton class method called _routes ... included do redefine_singleton_method(:_routes) { routes } end # And an instance method _routes. Note that # UrlFor (included in this module) add extra # conveniences for working with @_routes. define_method(:_routes) { @_routes || routes } define_method(:_generate_paths_by_default) do supports_path end 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 19
alias inspect to_s
#make_request(env) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 404
def make_request(env) request_class.new env 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 477
def mounted_helpers MountedHelpers end
#path_for(options, route_name = nil, reserved = RESERVED_OPTIONS)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 826
def path_for(, route_name = nil, reserved = RESERVED_OPTIONS) url_for(, route_name, PATH, nil, reserved) end
#prepend(&block)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 439
def prepend(&block) @prepend << block end
#recognize_path(path, environment = {})
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 885
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)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 900
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::DEFAULT_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
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 392
def relative_url_root @config.relative_url_root end
#request_class
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 400
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 831
def url_for(, route_name = nil, url_strategy = UNKNOWN, method_name = nil, reserved = RESERVED_OPTIONS) = .merge user = password = nil if [:user] && [:password] user = .delete :user password = .delete :password end 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 = .dup reserved.each { |ro| .delete ro } 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 [:user] = user [:password] = password url_strategy.call end
#url_helpers(supports_path = true)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 500
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