Class: Jets::Router::Matcher
- Inherits:
-
Object
- Object
- Jets::Router::Matcher
- Extended by:
- Memoist
- Defined in:
- lib/jets/router/matcher.rb
Instance Attribute Summary collapse
-
#routes ⇒ Object
readonly
Returns the value of attribute routes.
Instance Method Summary collapse
-
#constraints_matches?(route) ⇒ Boolean
Matcher called in mimic.rb before mimic event is available We need to extract the parameters from the possible matching route directly since event is unavailable.
- #find_by_controller_action(controller, action) ⇒ Object
-
#find_by_env(env) ⇒ Object
Simpler version of find_by_request that does not check constraints.
-
#find_by_request(request, request_method = nil) ⇒ Object
Precedence: 1.
- #find_engine_route(route) ⇒ Object
- #find_route ⇒ Object
-
#initialize(route_set = Jets.application.routes) ⇒ Matcher
constructor
A new instance of Matcher.
- #match?(route) ⇒ Boolean
- #match_constraints(route) ⇒ Object
- #mount ⇒ Object
- #request_method ⇒ Object
- #request_path ⇒ Object
- #strip_format(path) ⇒ Object
Constructor Details
#initialize(route_set = Jets.application.routes) ⇒ Matcher
Returns a new instance of Matcher.
6 7 8 9 |
# File 'lib/jets/router/matcher.rb', line 6 def initialize(route_set=Jets.application.routes) @route_set = route_set @routes = route_set.ordered_routes end |
Instance Attribute Details
#routes ⇒ Object (readonly)
Returns the value of attribute routes.
5 6 7 |
# File 'lib/jets/router/matcher.rb', line 5 def routes @routes end |
Instance Method Details
#constraints_matches?(route) ⇒ Boolean
Matcher called in mimic.rb before mimic event is available We need to extract the parameters from the possible matching route directly since event is unavailable.
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/jets/router/matcher.rb', line 127 def constraints_matches?(route) # Matcher is used super-early when request not yet available. # Cannot check constraints because we dont have the request object. # To build a request object, would need to build a mimic event and it's not yet available. return true if @request.nil? constraints = route.constraints return true if constraints.blank? if constraints.is_a?(Hash) parameters = route.extract_parameters(request_path) # extract directly constraints.any? do |key, value| key = key.to_s if value.is_a?(Regexp) value.match(parameters[key]) else # String if parameters[key] value == parameters[key] elsif @request.respond_to?(key) value == @request.send(key) end end end elsif constraints.respond_to?(:call) constraints.call(@request) elsif constraints.respond_to?(:matches?) constraints.matches?(@request) end end |
#find_by_controller_action(controller, action) ⇒ Object
50 51 52 53 54 55 56 |
# File 'lib/jets/router/matcher.rb', line 50 def find_by_controller_action(controller, action) controller = "#{controller.camelize}Controller" routes.find do |r| r.controller_name == controller.to_s && r.action_name == action.to_s end end |
#find_by_env(env) ⇒ Object
Simpler version of find_by_request that does not check constraints. Used by Jets::Controller::Middleware::Mimic and called super-early on. Does not have access to @request object and path_params
43 44 45 46 47 48 |
# File 'lib/jets/router/matcher.rb', line 43 def find_by_env(env) @env = env @request_method = env["REQUEST_METHOD"] || "GET" @request_path = strip_format(env["PATH_INFO"]) find_route end |
#find_by_request(request, request_method = nil) ⇒ Object
Precedence:
-
Routes with no captures get highest precedence: posts/new
-
Then we consider the routes with captures: post/:id
Within these 2 groups we consider the routes with the longest path first since posts/:id and posts/:id/edit can both match.
30 31 32 33 34 35 36 37 38 |
# File 'lib/jets/router/matcher.rb', line 30 def find_by_request(request, request_method=nil) @request = request # @request is used to check constraints # Checking the request_method_from_hidden_method_field so that handler can find the right route # super early in the process. Otherwise lambda routes to the wrong controller action. @request_method = request_method || @request.request_method_from_hidden_method_field || @request.request_method.to_s.upcase @request_path = strip_format(@request.path) route = find_route match_constraints(route) if route end |
#find_engine_route(route) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/jets/router/matcher.rb', line 71 def find_engine_route(route) return unless mount engine_matcher = self.class.new(route.engine.route_set) engine_route = if @request engine_matcher.find_by_request(@request, @request_method) else engine_matcher.find_by_env(@env) end # save original engine for route.extract_parameters later engine_route.original_engine = route.engine if engine_route engine_route end |
#find_route ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/jets/router/matcher.rb', line 58 def find_route routes.each do |r| if r.engine route = find_engine_route(r) return route if route else found = match?(r) return r if found end end nil end |
#match?(route) ⇒ Boolean
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/jets/router/matcher.rb', line 94 def match?(route) # Immediately stop checking when the request http_method: GET, POST, ANY, etc # doesnt match. return false if request_method != route.http_method && route.http_method != "ANY" route_path = strip_format(route.path) route_path = "#{mount.at}#{route_path}" if mount if request_path == route_path # regular string match detection return true # exact route matches are highest precedence end # Check path for route capture and wildcard matches: # A colon (:) means the variable has a variable if route_path.include?(':') # 2nd highest precedence capture_detection(route_path, request_path) # early return true or false # A star (*) means the variable has a glob elsif route_path.include?('*') # lowest precedence proxy_detection(route_path, request_path) # early return true or false else false # reach here, means no route matched end end |
#match_constraints(route) ⇒ Object
119 120 121 122 |
# File 'lib/jets/router/matcher.rb', line 119 def match_constraints(route) return unless route constraints_matches?(route) ? route : nil end |
#mount ⇒ Object
85 86 87 |
# File 'lib/jets/router/matcher.rb', line 85 def mount EngineMount.find_by(request_path: request_path) end |
#request_method ⇒ Object
20 21 22 |
# File 'lib/jets/router/matcher.rb', line 20 def request_method @request_method.to_s.upcase if @request_method end |
#request_path ⇒ Object
11 12 13 14 15 16 17 18 |
# File 'lib/jets/router/matcher.rb', line 11 def request_path # Ensure leading slash # Be more forgiving and allow the request_path to be passed in without a leading slash. # Note: request PATH_INFO will always have a leading slash, but just in case. # This is also covered in specs. return unless @request_path @request_path.starts_with?('/') ? @request_path : "/#{@request_path}" end |
#strip_format(path) ⇒ Object
90 91 92 |
# File 'lib/jets/router/matcher.rb', line 90 def strip_format(path) path.sub(/\..+$/, '') # Remove format from the end of the path end |