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 365Config.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 811[: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 335->( ) { 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 367
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 344
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 348
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 398
def api_only? @config.api_only end
#default_scope (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 337
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
#default_url_options (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 339
attr_accessor :, :draw_paths
#disable_clear_and_finalize (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 338
attr_accessor :disable_clear_and_finalize, :resources_path_names
#draw_paths (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 339
attr_accessor :, :draw_paths
#empty? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 612
def empty? routes.empty? end
#env_key (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 340
attr_reader :env_key, :polymorphic_mappings
#formatter (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 337
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
#named_routes (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 337
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 815
def optimize_routes_generation? .empty? end
#polymorphic_mappings (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 340
attr_reader :env_key, :polymorphic_mappings
#resources_path_names (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 338
attr_accessor :disable_clear_and_finalize, :resources_path_names
#router (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 337
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
#routes (readonly)
Alias for #set.
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 342
alias :routes :set
#set (rw) Also known as: #routes
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 337
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 647
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 616
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 651
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 437
def append(&block) @append << block end
#call(env)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 876
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 461
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 411
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 482
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 430
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 445
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 791
def extra_keys(, recall = {}) generate_extras(, recall).last end
#finalize!
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 455
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 819
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 795
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 509
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 20
alias inspect to_s
#make_request(env) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 406
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 478
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 823
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 441
def prepend(&block) @prepend << block end
#recognize_path(path, environment = {})
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 882
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 897
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 394
def relative_url_root @config.relative_url_root end
#request_class
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 402
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 828
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 501
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