Skip to content

Commit 9e38298

Browse files
authored
Merge pull request rails#54526 from skipkayhil/hm-avoid-array-methods
More Journey optimizations
2 parents 7e0fab6 + cc7c359 commit 9e38298

File tree

4 files changed

+61
-49
lines changed

4 files changed

+61
-49
lines changed

actionpack/lib/action_dispatch/journey/route.rb

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -38,29 +38,50 @@ def self.call(_); true; end
3838
def self.verb; ""; end
3939
end
4040

41+
class Or
42+
attr_reader :verb
43+
44+
def initialize(verbs)
45+
@verbs = verbs
46+
@verb = @verbs.map(&:verb).join("|")
47+
end
48+
49+
def call(req)
50+
@verbs.any? { |v| v.call req }
51+
end
52+
end
53+
4154
VERB_TO_CLASS = VERBS.each_with_object(all: All) do |verb, hash|
4255
klass = const_get verb
4356
hash[verb] = klass
4457
hash[verb.downcase] = klass
4558
hash[verb.downcase.to_sym] = klass
4659
end
47-
end
4860

49-
def self.verb_matcher(verb)
50-
VerbMatchers::VERB_TO_CLASS.fetch(verb) do
61+
VERB_TO_CLASS.default_proc = proc do |_, verb|
5162
VerbMatchers::Unknown.new verb.to_s.dasherize.upcase
5263
end
64+
65+
def self.for(verbs)
66+
if verbs.any? { |v| VERB_TO_CLASS[v] == All }
67+
All
68+
elsif verbs.one?
69+
VERB_TO_CLASS[verbs.first]
70+
else
71+
Or.new(verbs.map { |v| VERB_TO_CLASS[v] })
72+
end
73+
end
5374
end
5475

5576
##
5677
# +path+ is a path constraint.
5778
# `constraints` is a hash of constraints to be applied to this route.
58-
def initialize(name:, app: nil, path:, constraints: {}, required_defaults: [], defaults: {}, request_method_match: nil, precedence: 0, scope_options: {}, internal: false, source_location: nil)
79+
def initialize(name:, app: nil, path:, constraints: {}, required_defaults: [], defaults: {}, via: nil, precedence: 0, scope_options: {}, internal: false, source_location: nil)
5980
@name = name
6081
@app = app
6182
@path = path
6283

63-
@request_method_match = request_method_match
84+
@request_method_match = via && VerbMatchers.for(via)
6485
@constraints = constraints
6586
@defaults = defaults
6687
@required_defaults = nil
@@ -146,43 +167,36 @@ def dispatcher?
146167
end
147168

148169
def matches?(request)
149-
match_verb(request) &&
150-
constraints.all? { |method, value|
151-
case value
152-
when Regexp, String
153-
value === request.send(method).to_s
154-
when Array
155-
value.include?(request.send(method))
156-
when TrueClass
157-
request.send(method).present?
158-
when FalseClass
159-
request.send(method).blank?
160-
else
161-
value === request.send(method)
162-
end
163-
}
170+
@request_method_match.call(request) && (
171+
constraints.empty? ||
172+
constraints.all? { |method, value|
173+
case value
174+
when Regexp, String
175+
value === request.send(method).to_s
176+
when Array
177+
value.include?(request.send(method))
178+
when TrueClass
179+
request.send(method).present?
180+
when FalseClass
181+
request.send(method).blank?
182+
else
183+
value === request.send(method)
184+
end
185+
}
186+
)
164187
end
165188

166189
def ip
167190
constraints[:ip] || //
168191
end
169192

170193
def requires_matching_verb?
171-
!@request_method_match.all? { |x| x == VerbMatchers::All }
194+
@request_method_match != VerbMatchers::All
172195
end
173196

174197
def verb
175-
verbs.join("|")
198+
@request_method_match.verb
176199
end
177-
178-
private
179-
def verbs
180-
@request_method_match.map(&:verb)
181-
end
182-
183-
def match_verb(request)
184-
@request_method_match.any? { |m| m.call request }
185-
end
186200
end
187201
end
188202
# :startdoc:

actionpack/lib/action_dispatch/journey/router.rb

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,12 @@ def serve(req)
3838
req.path_info = "/" + req.path_info unless req.path_info.start_with? "/"
3939
end
4040

41-
tmp_params = set_params.merge route.defaults
42-
parameters.each_pair { |key, val|
43-
tmp_params[key] = val.force_encoding(::Encoding::UTF_8)
44-
}
45-
46-
req.path_parameters = tmp_params
41+
req.path_parameters = parameters
4742
req.route = route
4843

4944
_, headers, _ = response = route.app.serve(req)
5045

51-
if "pass" == headers[Constants::X_CASCADE]
46+
if headers[Constants::X_CASCADE] == "pass"
5247
req.script_name = script_name
5348
req.path_info = path_info
5449
req.path_parameters = set_params
@@ -69,7 +64,6 @@ def recognize(rails_req)
6964
rails_req.path_info = "/" + rails_req.path_info unless rails_req.path_info.start_with? "/"
7065
end
7166

72-
parameters = route.defaults.merge parameters
7367
yield(route, parameters)
7468
end
7569
end
@@ -107,8 +101,10 @@ def filter_routes(path)
107101

108102
def find_routes(req)
109103
path_info = req.path_info
110-
routes = filter_routes(path_info).concat custom_routes.find_all { |r|
111-
r.path.match?(path_info)
104+
routes = filter_routes(path_info)
105+
106+
custom_routes.each { |r|
107+
routes << r if r.path.match?(path_info)
112108
}
113109

114110
if req.head?
@@ -125,15 +121,19 @@ def find_routes(req)
125121

126122
routes.each do |r|
127123
match_data = r.path.match(path_info)
128-
path_parameters = {}
124+
125+
path_parameters = req.path_parameters.merge r.defaults
126+
129127
index = 1
130128
match_data.names.each do |name|
131129
if val = match_data[index]
132-
path_parameters[name.to_sym] = if val.include?("%")
130+
val = if val.include?("%")
133131
CGI.unescapeURIComponent(val)
134132
else
135133
val
136134
end
135+
val.force_encoding(::Encoding::UTF_8)
136+
path_parameters[name.to_sym] = val
137137
end
138138
index += 1
139139
end

actionpack/lib/action_dispatch/routing/mapper.rb

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ def initialize(set:, ast:, controller:, default_action:, to:, formatted:, via:,
183183
def make_route(name, precedence)
184184
Journey::Route.new(name: name, app: application, path: path, constraints: conditions,
185185
required_defaults: required_defaults, defaults: defaults,
186-
request_method_match: request_method, precedence: precedence,
186+
via: @via, precedence: precedence,
187187
scope_options: scope_options, internal: @internal, source_location: route_source_location)
188188
end
189189

@@ -204,11 +204,6 @@ def build_conditions(current_conditions, request_class)
204204
end
205205
private :build_conditions
206206

207-
def request_method
208-
@via.map { |x| Journey::Route.verb_matcher(x) }
209-
end
210-
private :request_method
211-
212207
private
213208
def intern(object)
214209
object.is_a?(String) ? -object : object

actionpack/lib/action_dispatch/routing/route_set.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,7 @@ def recognize_path_with_request(req, path, extras, raise_on_missing: true)
932932
params[key] = URI::RFC2396_PARSER.unescape(value)
933933
end
934934
end
935+
original_path_parameters = req.path_parameters
935936
req.path_parameters = params
936937
app = route.app
937938
if app.matches?(req) && app.dispatcher?
@@ -945,6 +946,8 @@ def recognize_path_with_request(req, path, extras, raise_on_missing: true)
945946
elsif app.matches?(req) && app.engine?
946947
path_parameters = app.rack_app.routes.recognize_path_with_request(req, path, extras, raise_on_missing: false)
947948
return path_parameters if path_parameters
949+
else
950+
req.path_parameters = original_path_parameters
948951
end
949952
end
950953

0 commit comments

Comments
 (0)