Class: ActionDispatch::Routing::Mapper::Mapping
Do not use. This class is for internal use only.
Relationships & Source Files | |
Inherits: | Object |
Defined in: | actionpack/lib/action_dispatch/routing/mapper.rb |
Constant Summary
-
ANCHOR_CHARACTERS_REGEX =
# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 84%r{\A(\\A|\^)|(\\Z|\\z|\$)\Z}
-
JOINED_SEPARATORS =
# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 181SEPARATORS.join
-
OPTIONAL_FORMAT_REGEX =
# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 85%r{(?:\(\.:format\)+|\.:format|/)\Z}
Class Method Summary
- .build(scope, set, ast, controller, default_action, to, via, formatted, options_constraints, anchor, options)
- .check_via(via)
- .new(set:, ast:, controller:, default_action:, to:, formatted:, via:, options_constraints:, anchor:, scope_params:, options:) ⇒ Mapping constructor
- .normalize_path(path, format)
- .optional_format?(path, format) ⇒ Boolean
Instance Attribute Summary
- #ast readonly
- #default_action readonly
- #default_controller readonly
- #defaults readonly
- #path readonly
- #required_defaults readonly
- #requirements readonly
- #scope_options readonly
- #to readonly
Instance Method Summary
- #application
- #conditions
- #make_route(name, precedence)
- #add_controller_module(controller, modyoule) private
- #app(blocks) private
- #blocks(callable_constraint) private
- #build_conditions(current_conditions, request_class) private
- #check_controller_and_action(path_params, controller, action) private
- #check_part(name, part, path_params, hash) private
- #constraints(options, path_params) private
- #dispatcher(raise_on_name_error) private
- #intern(object) private
- #normalize_defaults(options) private
- #normalize_format(formatted) private
- #normalize_options!(options, path_params, modyoule) private
- #request_method private
- #route_source_location private
- #split_constraints(path_params, constraints) private
- #translate_controller(controller) private
- #verify_regexp_requirements(requirements, wildcard_options) private
Constructor Details
.new(set:, ast:, controller:, default_action:, to:, formatted:, via:, options_constraints:, anchor:, scope_params:, options:) ⇒ Mapping
# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 132
def initialize(set:, ast:, controller:, default_action:, to:, formatted:, via:, options_constraints:, anchor:, scope_params:, options:) @defaults = scope_params[:defaults] @set = set @to = intern(to) @default_controller = intern(controller) @default_action = intern(default_action) @anchor = anchor @via = via @internal = .delete(:internal) @scope_options = scope_params[: ] ast = Journey::Ast.new(ast, formatted) = ast. .merge!( ) = (, ast.path_params, scope_params[:module]) = constraints(, ast.path_params) constraints = scope_params[:constraints].merge Hash[ [:constraints] || []] if .is_a?(Hash) @defaults = Hash[ .find_all { |key, default| URL_OPTIONS.include?(key) && (String === default || Integer === default) }].merge @defaults @blocks = scope_params[:blocks] constraints.merge! else @blocks = blocks( ) end requirements, conditions = split_constraints ast.path_params, constraints verify_regexp_requirements requirements, ast. formats = normalize_format(formatted) @requirements = formats[:requirements].merge Hash[requirements] @conditions = Hash[conditions] @defaults = formats[:defaults].merge(@defaults).merge(normalize_defaults( )) if ast.path_params.include?(:action) && !@requirements.key?(:action) @defaults[:action] ||= "index" end @required_defaults = ( [:required_defaults] || []).map(&:first) ast.requirements = @requirements @path = Journey::Path::Pattern.new(ast, @requirements, JOINED_SEPARATORS, @anchor) end
Class Method Details
.build(scope, set, ast, controller, default_action, to, via, formatted, options_constraints, anchor, options)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 90
def self.build(scope, set, ast, controller, default_action, to, via, formatted, , anchor, ) scope_params = { blocks: scope[:blocks] || [], constraints: scope[:constraints] || {}, defaults: (scope[:defaults] || {}).dup, module: scope[:module], options: scope[: ] || {} } new set: set, ast: ast, controller: controller, default_action: default_action, to: to, formatted: formatted, via: via, options_constraints: , anchor: anchor, scope_params: scope_params, options: scope_params[: ].merge( ) end
.check_via(via)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 104
def self.check_via(via) if via.empty? msg = "You should not use the `match` method in your router without specifying an HTTP method.\n" \ "If you want to expose your action to both GET and POST, add `via: [:get, :post]` option.\n" \ "If you want to expose your action to GET, use `get` in the router:\n" \ " Instead of: match \"controller#action\"\n" \ " Do: get \"controller#action\"" raise ArgumentError, msg end via end
.normalize_path(path, format)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 116
def self.normalize_path(path, format) path = Mapper.normalize_path(path) if format == true "#{path}.:format" elsif optional_format?(path, format) "#{path}(.:format)" else path end end
.optional_format?(path, format) ⇒ Boolean
# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 128
def self.optional_format?(path, format) format != false && !path.match?(OPTIONAL_FORMAT_REGEX) end
Instance Attribute Details
#ast (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 87
attr_reader :path, :requirements, :defaults, :to, :default_controller, :default_action, :required_defaults, :ast, :
#default_action (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 87
attr_reader :path, :requirements, :defaults, :to, :default_controller, :default_action, :required_defaults, :ast, :
#default_controller (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 87
attr_reader :path, :requirements, :defaults, :to, :default_controller, :default_action, :required_defaults, :ast, :
#defaults (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 87
attr_reader :path, :requirements, :defaults, :to, :default_controller, :default_action, :required_defaults, :ast, :
#path (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 87
attr_reader :path, :requirements, :defaults, :to, :default_controller, :default_action, :required_defaults, :ast, :
#required_defaults (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 87
attr_reader :path, :requirements, :defaults, :to, :default_controller, :default_action, :required_defaults, :ast, :
#requirements (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 87
attr_reader :path, :requirements, :defaults, :to, :default_controller, :default_action, :required_defaults, :ast, :
#scope_options (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 87
attr_reader :path, :requirements, :defaults, :to, :default_controller, :default_action, :required_defaults, :ast, :
#to (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 87
attr_reader :path, :requirements, :defaults, :to, :default_controller, :default_action, :required_defaults, :ast, :
Instance Method Details
#add_controller_module(controller, modyoule) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 334
def add_controller_module(controller, modyoule) if modyoule && !controller.is_a?(Regexp) if controller&.start_with?("/") -controller[1..-1] else -[modyoule, controller].compact.join("/") end else controller end end
#app(blocks) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 295
def app(blocks) if to.respond_to?(:action) Routing::RouteSet::StaticDispatcher.new to elsif to.respond_to?(:call) Constraints.new(to, blocks, Constraints::CALL) elsif blocks.any? Constraints.new(dispatcher(defaults.key?(:controller)), blocks, Constraints::SERVE) else dispatcher(defaults.key?(:controller)) end end
#application
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 190
def application app(@blocks) end
#blocks(callable_constraint) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 353
def blocks(callable_constraint) unless callable_constraint.respond_to?(:call) || callable_constraint.respond_to?(:matches?) raise ArgumentError, "Invalid constraint: #{callable_constraint.inspect} must respond to :call or :matches?" end [callable_constraint] end
#build_conditions(current_conditions, request_class) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 198
def build_conditions(current_conditions, request_class) conditions = current_conditions.dup conditions.keep_if do |k, _| request_class.public_method_defined?(k) end end
#check_controller_and_action(path_params, controller, action) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 307
def check_controller_and_action(path_params, controller, action) hash = check_part(:controller, controller, path_params, {}) do |part| translate_controller(part) { = +"'#{part}' is not a supported controller name. This can lead to potential routing problems." << " See https://guides.rubyonrails.org/routing.html#specifying-a-controller-to-use" raise ArgumentError, } end check_part(:action, action, path_params, hash) { |part| part.is_a?(Regexp) ? part : part.to_s } end
#check_part(name, part, path_params, hash) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 322
def check_part(name, part, path_params, hash) if part hash[name] = yield(part) else unless path_params.include?(name) = "Missing :#{name} key on routes definition, please check your routes." raise ArgumentError, end end hash end
#conditions
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 194
def conditions build_conditions @conditions, @set.request_class end
#constraints(options, path_params) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 360
def constraints(, path_params) .group_by do |key, option| if Regexp === option :constraints else if path_params.include?(key) :path_params else :required_defaults end end end end
#dispatcher(raise_on_name_error) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 374
def dispatcher(raise_on_name_error) Routing::RouteSet::Dispatcher.new raise_on_name_error end
#intern(object) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 213
def intern(object) object.is_a?(String) ? -object : object end
#make_route(name, precedence)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 183
def make_route(name, precedence) Journey::Route.new(name: name, app: application, path: path, constraints: conditions, required_defaults: required_defaults, defaults: defaults, request_method_match: request_method, precedence: precedence, scope_options: , internal: @internal, source_location: route_source_location) end
#normalize_defaults(options) (private)
[ GitHub ]#normalize_format(formatted) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 259
def normalize_format(formatted) case formatted when true { requirements: { format: /.+/ }, defaults: {} } when Regexp { requirements: { format: formatted }, defaults: { format: nil } } when String { requirements: { format: Regexp.compile(formatted) }, defaults: { format: formatted } } else { requirements: {}, defaults: {} } end end
#normalize_options!(options, path_params, modyoule) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 217
def (, path_params, modyoule) if path_params.include?(:controller) raise ArgumentError, ":controller segment is not allowed within a namespace block" if modyoule # Add a default constraint for :controller path segments that matches namespaced # controllers with default routes like :controller/:action/:id(.:format), e.g: # GET /admin/products/show/1 # # > { controller: 'admin/products', action: 'show', id: '1' } [:controller] ||= /.+?/ end if to.respond_to?(:action) || to.respond_to?(:call) else if to.nil? controller = default_controller action = default_action elsif to.is_a?(String) if to.include?("#") to_endpoint = to.split("#").map!(&:-@) controller = to_endpoint[0] action = to_endpoint[1] else controller = default_controller action = to end else raise ArgumentError, ":to must respond to `action` or `call`, or it must be a String that includes '#', or the controller should be implicit" end controller = add_controller_module(controller, modyoule) .merge! check_controller_and_action(path_params, controller, action) end end
#request_method (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 207
def request_method @via.map { |x| Journey::Route.verb_matcher(x) } end
#route_source_location (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 378
def route_source_location if Mapper.route_source_locations action_dispatch_dir = File. ("..", __dir__) Thread.each_caller_location do |location| next if location.path.start_with?(action_dispatch_dir) cleaned_path = Mapper.backtrace_cleaner.clean_frame(location.path) next if cleaned_path.nil? return "#{cleaned_path}:#{location.lineno}" end nil end end
#split_constraints(path_params, constraints) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 253
def split_constraints(path_params, constraints) constraints.partition do |key, requirement| path_params.include?(key) || key == :controller end end
#translate_controller(controller) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 346
def translate_controller(controller) return controller if Regexp === controller return controller.to_s if /\A[a-z_0-9][a-z_0-9\/]*\z/.match?(controller) yield end
#verify_regexp_requirements(requirements, wildcard_options) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 275
def verify_regexp_requirements(requirements, ) requirements.each do |requirement, regex| next unless regex.is_a? Regexp if ANCHOR_CHARACTERS_REGEX.match?(regex.source) raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}" end if regex.multiline? next if .key?(requirement) raise ArgumentError, "Regexp multiline option is not allowed in routing requirements: #{regex.inspect}" end end end