actionpack 4.1.7 → 4.2.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +311 -527
- data/README.rdoc +7 -2
- data/lib/abstract_controller/base.rb +16 -6
- data/lib/abstract_controller/callbacks.rb +28 -51
- data/lib/abstract_controller/helpers.rb +11 -4
- data/lib/abstract_controller/railties/routes_helpers.rb +3 -3
- data/lib/abstract_controller/url_for.rb +1 -1
- data/lib/action_controller/base.rb +2 -1
- data/lib/action_controller/caching/fragments.rb +7 -1
- data/lib/action_controller/caching.rb +1 -1
- data/lib/action_controller/log_subscriber.rb +26 -26
- data/lib/action_controller/metal/conditional_get.rb +37 -12
- data/lib/action_controller/metal/etag_with_template_digest.rb +50 -0
- data/lib/action_controller/metal/exceptions.rb +1 -1
- data/lib/action_controller/metal/force_ssl.rb +1 -1
- data/lib/action_controller/metal/head.rb +7 -3
- data/lib/action_controller/metal/http_authentication.rb +14 -9
- data/lib/action_controller/metal/instrumentation.rb +8 -5
- data/lib/action_controller/metal/live.rb +57 -6
- data/lib/action_controller/metal/mime_responds.rb +23 -246
- data/lib/action_controller/metal/params_wrapper.rb +2 -2
- data/lib/action_controller/metal/rack_delegation.rb +1 -1
- data/lib/action_controller/metal/redirecting.rb +14 -8
- data/lib/action_controller/metal/renderers.rb +30 -10
- data/lib/action_controller/metal/rendering.rb +2 -6
- data/lib/action_controller/metal/request_forgery_protection.rb +78 -7
- data/lib/action_controller/metal/streaming.rb +1 -1
- data/lib/action_controller/metal/strong_parameters.rb +125 -12
- data/lib/action_controller/metal/url_for.rb +11 -12
- data/lib/action_controller/metal.rb +12 -11
- data/lib/action_controller/model_naming.rb +1 -1
- data/lib/action_controller/railtie.rb +4 -0
- data/lib/action_controller/test_case.rb +112 -75
- data/lib/action_controller.rb +1 -1
- data/lib/action_dispatch/http/cache.rb +5 -4
- data/lib/action_dispatch/http/filter_parameters.rb +2 -2
- data/lib/action_dispatch/http/headers.rb +43 -9
- data/lib/action_dispatch/http/mime_negotiation.rb +10 -3
- data/lib/action_dispatch/http/mime_type.rb +2 -2
- data/lib/action_dispatch/http/parameter_filter.rb +1 -1
- data/lib/action_dispatch/http/parameters.rb +11 -26
- data/lib/action_dispatch/http/request.rb +37 -11
- data/lib/action_dispatch/http/response.rb +70 -18
- data/lib/action_dispatch/http/upload.rb +3 -8
- data/lib/action_dispatch/http/url.rb +88 -69
- data/lib/action_dispatch/journey/formatter.rb +33 -17
- data/lib/action_dispatch/journey/gtg/builder.rb +3 -3
- data/lib/action_dispatch/journey/gtg/simulator.rb +10 -7
- data/lib/action_dispatch/journey/gtg/transition_table.rb +20 -28
- data/lib/action_dispatch/journey/nfa/dot.rb +2 -2
- data/lib/action_dispatch/journey/nfa/simulator.rb +1 -1
- data/lib/action_dispatch/journey/nfa/transition_table.rb +5 -5
- data/lib/action_dispatch/journey/nodes/node.rb +4 -0
- data/lib/action_dispatch/journey/parser.rb +52 -60
- data/lib/action_dispatch/journey/parser.y +11 -10
- data/lib/action_dispatch/journey/path/pattern.rb +16 -19
- data/lib/action_dispatch/journey/route.rb +3 -18
- data/lib/action_dispatch/journey/router/strexp.rb +9 -6
- data/lib/action_dispatch/journey/router.rb +53 -77
- data/lib/action_dispatch/journey/scanner.rb +5 -5
- data/lib/action_dispatch/journey/visitors.rb +81 -92
- data/lib/action_dispatch/journey/visualizer/fsm.css +0 -4
- data/lib/action_dispatch/journey/visualizer/index.html.erb +2 -2
- data/lib/action_dispatch/middleware/callbacks.rb +1 -1
- data/lib/action_dispatch/middleware/cookies.rb +29 -29
- data/lib/action_dispatch/middleware/debug_exceptions.rb +15 -4
- data/lib/action_dispatch/middleware/exception_wrapper.rb +50 -18
- data/lib/action_dispatch/middleware/flash.rb +13 -7
- data/lib/action_dispatch/middleware/params_parser.rb +1 -1
- data/lib/action_dispatch/middleware/public_exceptions.rb +12 -3
- data/lib/action_dispatch/middleware/remote_ip.rb +40 -54
- data/lib/action_dispatch/middleware/request_id.rb +1 -1
- data/lib/action_dispatch/middleware/session/cookie_store.rb +1 -1
- data/lib/action_dispatch/middleware/show_exceptions.rb +1 -0
- data/lib/action_dispatch/middleware/static.rb +66 -37
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +21 -19
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +37 -9
- data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +2 -8
- data/lib/action_dispatch/middleware/templates/rescues/{diagnostics.erb → diagnostics.html.erb} +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +6 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +4 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +2 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -24
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +0 -1
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +120 -64
- data/lib/action_dispatch/routing/endpoint.rb +10 -0
- data/lib/action_dispatch/routing/inspector.rb +5 -12
- data/lib/action_dispatch/routing/mapper.rb +410 -281
- data/lib/action_dispatch/routing/polymorphic_routes.rb +191 -79
- data/lib/action_dispatch/routing/redirection.rb +10 -12
- data/lib/action_dispatch/routing/route_set.rb +297 -168
- data/lib/action_dispatch/routing/url_for.rb +15 -4
- data/lib/action_dispatch/testing/assertions/dom.rb +2 -26
- data/lib/action_dispatch/testing/assertions/response.rb +2 -7
- data/lib/action_dispatch/testing/assertions/routing.rb +22 -22
- data/lib/action_dispatch/testing/assertions/selector.rb +2 -429
- data/lib/action_dispatch/testing/assertions/tag.rb +2 -134
- data/lib/action_dispatch/testing/assertions.rb +11 -7
- data/lib/action_dispatch/testing/integration.rb +24 -19
- data/lib/action_dispatch/testing/test_request.rb +1 -1
- data/lib/action_dispatch/testing/test_response.rb +7 -0
- data/lib/action_pack/gem_version.rb +3 -3
- metadata +55 -13
- data/lib/action_controller/metal/responder.rb +0 -297
@@ -101,118 +101,230 @@ module ActionDispatch
|
|
101
101
|
# polymorphic_url(Comment) # same as comments_url()
|
102
102
|
#
|
103
103
|
def polymorphic_url(record_or_hash_or_array, options = {})
|
104
|
-
if record_or_hash_or_array
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
end
|
109
|
-
record_or_hash_or_array = record_or_hash_or_array[0] if record_or_hash_or_array.size == 1
|
110
|
-
end
|
111
|
-
|
112
|
-
record = extract_record(record_or_hash_or_array)
|
113
|
-
record = convert_to_model(record)
|
114
|
-
|
115
|
-
args = Array === record_or_hash_or_array ?
|
116
|
-
record_or_hash_or_array.dup :
|
117
|
-
[ record_or_hash_or_array ]
|
118
|
-
|
119
|
-
inflection = if options[:action] && options[:action].to_s == "new"
|
120
|
-
args.pop
|
121
|
-
:singular
|
122
|
-
elsif (record.respond_to?(:persisted?) && !record.persisted?)
|
123
|
-
args.pop
|
124
|
-
:plural
|
125
|
-
elsif record.is_a?(Class)
|
126
|
-
args.pop
|
127
|
-
:plural
|
128
|
-
else
|
129
|
-
:singular
|
104
|
+
if Hash === record_or_hash_or_array
|
105
|
+
options = record_or_hash_or_array.merge(options)
|
106
|
+
record = options.delete :id
|
107
|
+
return polymorphic_url record, options
|
130
108
|
end
|
131
109
|
|
132
|
-
|
133
|
-
|
110
|
+
opts = options.dup
|
111
|
+
action = opts.delete :action
|
112
|
+
type = opts.delete(:routing_type) || :url
|
134
113
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
args.collect! { |a| convert_to_model(a) }
|
141
|
-
|
142
|
-
(proxy || self).send(named_route, *args)
|
114
|
+
HelperMethodBuilder.polymorphic_method self,
|
115
|
+
record_or_hash_or_array,
|
116
|
+
action,
|
117
|
+
type,
|
118
|
+
opts
|
143
119
|
end
|
144
120
|
|
145
121
|
# Returns the path component of a URL for the given record. It uses
|
146
122
|
# <tt>polymorphic_url</tt> with <tt>routing_type: :path</tt>.
|
147
123
|
def polymorphic_path(record_or_hash_or_array, options = {})
|
148
|
-
|
124
|
+
if Hash === record_or_hash_or_array
|
125
|
+
options = record_or_hash_or_array.merge(options)
|
126
|
+
record = options.delete :id
|
127
|
+
return polymorphic_path record, options
|
128
|
+
end
|
129
|
+
|
130
|
+
opts = options.dup
|
131
|
+
action = opts.delete :action
|
132
|
+
type = :path
|
133
|
+
|
134
|
+
HelperMethodBuilder.polymorphic_method self,
|
135
|
+
record_or_hash_or_array,
|
136
|
+
action,
|
137
|
+
type,
|
138
|
+
opts
|
149
139
|
end
|
150
140
|
|
141
|
+
|
151
142
|
%w(edit new).each do |action|
|
152
143
|
module_eval <<-EOT, __FILE__, __LINE__ + 1
|
153
|
-
def #{action}_polymorphic_url(record_or_hash, options = {})
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
polymorphic_url( # polymorphic_url(
|
161
|
-
record_or_hash, # record_or_hash,
|
162
|
-
options.merge(:action => "#{action}", :routing_type => :path)) # options.merge(:action => "edit", :routing_type => :path))
|
163
|
-
end # end
|
144
|
+
def #{action}_polymorphic_url(record_or_hash, options = {})
|
145
|
+
polymorphic_url_for_action("#{action}", record_or_hash, options)
|
146
|
+
end
|
147
|
+
|
148
|
+
def #{action}_polymorphic_path(record_or_hash, options = {})
|
149
|
+
polymorphic_path_for_action("#{action}", record_or_hash, options)
|
150
|
+
end
|
164
151
|
EOT
|
165
152
|
end
|
166
153
|
|
167
154
|
private
|
168
|
-
|
169
|
-
|
155
|
+
|
156
|
+
def polymorphic_url_for_action(action, record_or_hash, options)
|
157
|
+
polymorphic_url(record_or_hash, options.merge(:action => action))
|
158
|
+
end
|
159
|
+
|
160
|
+
def polymorphic_path_for_action(action, record_or_hash, options)
|
161
|
+
polymorphic_path(record_or_hash, options.merge(:action => action))
|
162
|
+
end
|
163
|
+
|
164
|
+
class HelperMethodBuilder # :nodoc:
|
165
|
+
CACHE = { 'path' => {}, 'url' => {} }
|
166
|
+
|
167
|
+
def self.get(action, type)
|
168
|
+
type = type.to_s
|
169
|
+
CACHE[type].fetch(action) { build action, type }
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.url; CACHE['url'.freeze][nil]; end
|
173
|
+
def self.path; CACHE['path'.freeze][nil]; end
|
174
|
+
|
175
|
+
def self.build(action, type)
|
176
|
+
prefix = action ? "#{action}_" : ""
|
177
|
+
suffix = type
|
178
|
+
if action.to_s == 'new'
|
179
|
+
HelperMethodBuilder.singular prefix, suffix
|
180
|
+
else
|
181
|
+
HelperMethodBuilder.plural prefix, suffix
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def self.singular(prefix, suffix)
|
186
|
+
new(->(name) { name.singular_route_key }, prefix, suffix)
|
170
187
|
end
|
171
188
|
|
172
|
-
def
|
173
|
-
|
189
|
+
def self.plural(prefix, suffix)
|
190
|
+
new(->(name) { name.route_key }, prefix, suffix)
|
174
191
|
end
|
175
192
|
|
176
|
-
def
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
end
|
193
|
+
def self.polymorphic_method(recipient, record_or_hash_or_array, action, type, options)
|
194
|
+
builder = get action, type
|
195
|
+
|
196
|
+
case record_or_hash_or_array
|
197
|
+
when Array
|
198
|
+
record_or_hash_or_array = record_or_hash_or_array.compact
|
199
|
+
if record_or_hash_or_array.empty?
|
200
|
+
raise ArgumentError, "Nil location provided. Can't build URI."
|
185
201
|
end
|
202
|
+
if record_or_hash_or_array.first.is_a?(ActionDispatch::Routing::RoutesProxy)
|
203
|
+
recipient = record_or_hash_or_array.shift
|
204
|
+
end
|
205
|
+
|
206
|
+
method, args = builder.handle_list record_or_hash_or_array
|
207
|
+
when String, Symbol
|
208
|
+
method, args = builder.handle_string record_or_hash_or_array
|
209
|
+
when Class
|
210
|
+
method, args = builder.handle_class record_or_hash_or_array
|
211
|
+
|
212
|
+
when nil
|
213
|
+
raise ArgumentError, "Nil location provided. Can't build URI."
|
214
|
+
else
|
215
|
+
method, args = builder.handle_model record_or_hash_or_array
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
if options.empty?
|
220
|
+
recipient.send(method, *args)
|
186
221
|
else
|
187
|
-
|
188
|
-
route = []
|
222
|
+
recipient.send(method, *args, options)
|
189
223
|
end
|
224
|
+
end
|
225
|
+
|
226
|
+
attr_reader :suffix, :prefix
|
227
|
+
|
228
|
+
def initialize(key_strategy, prefix, suffix)
|
229
|
+
@key_strategy = key_strategy
|
230
|
+
@prefix = prefix
|
231
|
+
@suffix = suffix
|
232
|
+
end
|
233
|
+
|
234
|
+
def handle_string(record)
|
235
|
+
[get_method_for_string(record), []]
|
236
|
+
end
|
237
|
+
|
238
|
+
def handle_string_call(target, str)
|
239
|
+
target.send get_method_for_string str
|
240
|
+
end
|
241
|
+
|
242
|
+
def handle_class(klass)
|
243
|
+
[get_method_for_class(klass), []]
|
244
|
+
end
|
245
|
+
|
246
|
+
def handle_class_call(target, klass)
|
247
|
+
target.send get_method_for_class klass
|
248
|
+
end
|
249
|
+
|
250
|
+
def handle_model(record)
|
251
|
+
args = []
|
252
|
+
|
253
|
+
model = record.to_model
|
254
|
+
name = if model.persisted?
|
255
|
+
args << model
|
256
|
+
model.model_name.singular_route_key
|
257
|
+
else
|
258
|
+
@key_strategy.call model.model_name
|
259
|
+
end
|
260
|
+
|
261
|
+
named_route = prefix + "#{name}_#{suffix}"
|
262
|
+
|
263
|
+
[named_route, args]
|
264
|
+
end
|
265
|
+
|
266
|
+
def handle_model_call(target, model)
|
267
|
+
method, args = handle_model model
|
268
|
+
target.send(method, *args)
|
269
|
+
end
|
270
|
+
|
271
|
+
def handle_list(list)
|
272
|
+
record_list = list.dup
|
273
|
+
record = record_list.pop
|
274
|
+
|
275
|
+
args = []
|
190
276
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
277
|
+
route = record_list.map { |parent|
|
278
|
+
case parent
|
279
|
+
when Symbol, String
|
280
|
+
parent.to_s
|
281
|
+
when Class
|
282
|
+
args << parent
|
283
|
+
parent.model_name.singular_route_key
|
196
284
|
else
|
197
|
-
|
285
|
+
args << parent.to_model
|
286
|
+
parent.to_model.model_name.singular_route_key
|
198
287
|
end
|
288
|
+
}
|
289
|
+
|
290
|
+
route <<
|
291
|
+
case record
|
292
|
+
when Symbol, String
|
293
|
+
record.to_s
|
294
|
+
when Class
|
295
|
+
@key_strategy.call record.model_name
|
199
296
|
else
|
200
|
-
|
297
|
+
model = record.to_model
|
298
|
+
if model.persisted?
|
299
|
+
args << model
|
300
|
+
model.model_name.singular_route_key
|
301
|
+
else
|
302
|
+
@key_strategy.call model.model_name
|
303
|
+
end
|
201
304
|
end
|
202
305
|
|
203
|
-
route <<
|
306
|
+
route << suffix
|
204
307
|
|
205
|
-
|
308
|
+
named_route = prefix + route.join("_")
|
309
|
+
[named_route, args]
|
206
310
|
end
|
207
311
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
312
|
+
private
|
313
|
+
|
314
|
+
def get_method_for_class(klass)
|
315
|
+
name = @key_strategy.call klass.model_name
|
316
|
+
prefix + "#{name}_#{suffix}"
|
317
|
+
end
|
318
|
+
|
319
|
+
def get_method_for_string(str)
|
320
|
+
prefix + "#{str}_#{suffix}"
|
214
321
|
end
|
322
|
+
|
323
|
+
[nil, 'new', 'edit'].each do |action|
|
324
|
+
CACHE['url'][action] = build action, 'url'
|
325
|
+
CACHE['path'][action] = build action, 'path'
|
326
|
+
end
|
327
|
+
end
|
215
328
|
end
|
216
329
|
end
|
217
330
|
end
|
218
|
-
|
@@ -3,10 +3,11 @@ require 'active_support/core_ext/uri'
|
|
3
3
|
require 'active_support/core_ext/array/extract_options'
|
4
4
|
require 'rack/utils'
|
5
5
|
require 'action_controller/metal/exceptions'
|
6
|
+
require 'action_dispatch/routing/endpoint'
|
6
7
|
|
7
8
|
module ActionDispatch
|
8
9
|
module Routing
|
9
|
-
class Redirect # :nodoc:
|
10
|
+
class Redirect < Endpoint # :nodoc:
|
10
11
|
attr_reader :status, :block
|
11
12
|
|
12
13
|
def initialize(status, block)
|
@@ -14,18 +15,15 @@ module ActionDispatch
|
|
14
15
|
@block = block
|
15
16
|
end
|
16
17
|
|
17
|
-
def
|
18
|
-
req = Request.new(env)
|
18
|
+
def redirect?; true; end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
unless value.valid_encoding?
|
24
|
-
raise ActionController::BadRequest, "Invalid parameter: #{key} => #{value}"
|
25
|
-
end
|
26
|
-
end
|
20
|
+
def call(env)
|
21
|
+
serve Request.new env
|
22
|
+
end
|
27
23
|
|
28
|
-
|
24
|
+
def serve(req)
|
25
|
+
req.check_path_parameters!
|
26
|
+
uri = URI.parse(path(req.path_parameters, req))
|
29
27
|
|
30
28
|
unless uri.host
|
31
29
|
if relative_path?(uri.path)
|
@@ -39,7 +37,7 @@ module ActionDispatch
|
|
39
37
|
uri.host ||= req.host
|
40
38
|
uri.port ||= req.port unless req.standard_port?
|
41
39
|
|
42
|
-
body = %(<html><body>You are being <a href="#{ERB::Util.
|
40
|
+
body = %(<html><body>You are being <a href="#{ERB::Util.unwrapped_html_escape(uri.to_s)}">redirected</a>.</body></html>)
|
43
41
|
|
44
42
|
headers = {
|
45
43
|
'Location' => uri.to_s,
|
@@ -6,39 +6,32 @@ require 'active_support/core_ext/object/to_query'
|
|
6
6
|
require 'active_support/core_ext/hash/slice'
|
7
7
|
require 'active_support/core_ext/module/remove_method'
|
8
8
|
require 'active_support/core_ext/array/extract_options'
|
9
|
+
require 'active_support/core_ext/string/filters'
|
9
10
|
require 'action_controller/metal/exceptions'
|
10
11
|
require 'action_dispatch/http/request'
|
12
|
+
require 'action_dispatch/routing/endpoint'
|
11
13
|
|
12
14
|
module ActionDispatch
|
13
15
|
module Routing
|
14
|
-
|
16
|
+
# :stopdoc:
|
17
|
+
class RouteSet
|
15
18
|
# Since the router holds references to many parts of the system
|
16
19
|
# like engines, controllers and the application itself, inspecting
|
17
20
|
# the route set can actually be really slow, therefore we default
|
18
21
|
# alias inspect to to_s.
|
19
22
|
alias inspect to_s
|
20
23
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
def initialize(options={})
|
25
|
-
@defaults = options[:defaults]
|
26
|
-
@glob_param = options.delete(:glob)
|
24
|
+
class Dispatcher < Routing::Endpoint
|
25
|
+
def initialize(defaults)
|
26
|
+
@defaults = defaults
|
27
27
|
@controller_class_names = ThreadSafe::Cache.new
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
31
|
-
params = env[PARAMETERS_KEY]
|
32
|
-
|
33
|
-
# If any of the path parameters has an invalid encoding then
|
34
|
-
# raise since it's likely to trigger errors further on.
|
35
|
-
params.each do |key, value|
|
36
|
-
next unless value.respond_to?(:valid_encoding?)
|
30
|
+
def dispatcher?; true; end
|
37
31
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
32
|
+
def serve(req)
|
33
|
+
req.check_path_parameters!
|
34
|
+
params = req.path_parameters
|
42
35
|
|
43
36
|
prepare_params!(params)
|
44
37
|
|
@@ -47,13 +40,12 @@ module ActionDispatch
|
|
47
40
|
return [404, {'X-Cascade' => 'pass'}, []]
|
48
41
|
end
|
49
42
|
|
50
|
-
dispatch(controller, params[:action], env)
|
43
|
+
dispatch(controller, params[:action], req.env)
|
51
44
|
end
|
52
45
|
|
53
46
|
def prepare_params!(params)
|
54
47
|
normalize_controller!(params)
|
55
48
|
merge_default_action!(params)
|
56
|
-
split_glob_param!(params) if @glob_param
|
57
49
|
end
|
58
50
|
|
59
51
|
# If this is a default_controller (i.e. a controller specified by the user)
|
@@ -89,47 +81,79 @@ module ActionDispatch
|
|
89
81
|
def merge_default_action!(params)
|
90
82
|
params[:action] ||= 'index'
|
91
83
|
end
|
92
|
-
|
93
|
-
def split_glob_param!(params)
|
94
|
-
params[@glob_param] = params[@glob_param].split('/').map { |v| URI.parser.unescape(v) }
|
95
|
-
end
|
96
84
|
end
|
97
85
|
|
98
86
|
# A NamedRouteCollection instance is a collection of named routes, and also
|
99
87
|
# maintains an anonymous module that can be used to install helpers for the
|
100
88
|
# named routes.
|
101
|
-
class NamedRouteCollection
|
89
|
+
class NamedRouteCollection
|
102
90
|
include Enumerable
|
103
|
-
attr_reader :routes, :
|
91
|
+
attr_reader :routes, :url_helpers_module
|
104
92
|
|
105
93
|
def initialize
|
106
94
|
@routes = {}
|
107
|
-
@
|
108
|
-
@
|
95
|
+
@path_helpers = Set.new
|
96
|
+
@url_helpers = Set.new
|
97
|
+
@url_helpers_module = Module.new
|
98
|
+
@path_helpers_module = Module.new
|
99
|
+
end
|
100
|
+
|
101
|
+
def route_defined?(name)
|
102
|
+
key = name.to_sym
|
103
|
+
@path_helpers.include?(key) || @url_helpers.include?(key)
|
104
|
+
end
|
105
|
+
|
106
|
+
def helpers
|
107
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
108
|
+
`named_routes.helpers` is deprecated, please use `route_defined?(route_name)`
|
109
|
+
to see if a named route was defined.
|
110
|
+
MSG
|
111
|
+
@path_helpers + @url_helpers
|
109
112
|
end
|
110
113
|
|
111
114
|
def helper_names
|
112
|
-
@
|
115
|
+
@path_helpers.map(&:to_s) + @url_helpers.map(&:to_s)
|
113
116
|
end
|
114
117
|
|
115
118
|
def clear!
|
116
|
-
@
|
117
|
-
@
|
119
|
+
@path_helpers.each do |helper|
|
120
|
+
@path_helpers_module.send :undef_method, helper
|
121
|
+
end
|
122
|
+
|
123
|
+
@url_helpers.each do |helper|
|
124
|
+
@url_helpers_module.send :undef_method, helper
|
118
125
|
end
|
119
126
|
|
120
127
|
@routes.clear
|
121
|
-
@
|
128
|
+
@path_helpers.clear
|
129
|
+
@url_helpers.clear
|
122
130
|
end
|
123
131
|
|
124
132
|
def add(name, route)
|
125
|
-
|
126
|
-
|
133
|
+
key = name.to_sym
|
134
|
+
path_name = :"#{name}_path"
|
135
|
+
url_name = :"#{name}_url"
|
136
|
+
|
137
|
+
if routes.key? key
|
138
|
+
@path_helpers_module.send :undef_method, path_name
|
139
|
+
@url_helpers_module.send :undef_method, url_name
|
140
|
+
end
|
141
|
+
routes[key] = route
|
142
|
+
define_url_helper @path_helpers_module, route, path_name, route.defaults, name, LEGACY
|
143
|
+
define_url_helper @url_helpers_module, route, url_name, route.defaults, name, UNKNOWN
|
144
|
+
|
145
|
+
@path_helpers << path_name
|
146
|
+
@url_helpers << url_name
|
127
147
|
end
|
128
148
|
|
129
149
|
def get(name)
|
130
150
|
routes[name.to_sym]
|
131
151
|
end
|
132
152
|
|
153
|
+
def key?(name)
|
154
|
+
routes.key? name.to_sym
|
155
|
+
end
|
156
|
+
|
133
157
|
alias []= add
|
134
158
|
alias [] get
|
135
159
|
alias clear clear!
|
@@ -147,36 +171,54 @@ module ActionDispatch
|
|
147
171
|
routes.length
|
148
172
|
end
|
149
173
|
|
150
|
-
|
151
|
-
|
174
|
+
def path_helpers_module(warn = false)
|
175
|
+
if warn
|
176
|
+
mod = @path_helpers_module
|
177
|
+
helpers = @path_helpers
|
178
|
+
Module.new do
|
179
|
+
include mod
|
180
|
+
|
181
|
+
helpers.each do |meth|
|
182
|
+
define_method(meth) do |*args, &block|
|
183
|
+
ActiveSupport::Deprecation.warn("The method `#{meth}` cannot be used here as a full URL is required. Use `#{meth.to_s.sub(/_path$/, '_url')}` instead")
|
184
|
+
super(*args, &block)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
else
|
189
|
+
@path_helpers_module
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
class UrlHelper
|
194
|
+
def self.create(route, options, route_name, url_strategy)
|
152
195
|
if optimize_helper?(route)
|
153
|
-
OptimizedUrlHelper.new(route, options)
|
196
|
+
OptimizedUrlHelper.new(route, options, route_name, url_strategy)
|
154
197
|
else
|
155
|
-
new route, options
|
198
|
+
new route, options, route_name, url_strategy
|
156
199
|
end
|
157
200
|
end
|
158
201
|
|
159
202
|
def self.optimize_helper?(route)
|
160
|
-
!route.glob? && route.requirements.
|
203
|
+
!route.glob? && route.path.requirements.empty?
|
161
204
|
end
|
162
205
|
|
163
|
-
|
206
|
+
attr_reader :url_strategy, :route_name
|
207
|
+
|
208
|
+
class OptimizedUrlHelper < UrlHelper
|
164
209
|
attr_reader :arg_size
|
165
210
|
|
166
|
-
def initialize(route, options)
|
211
|
+
def initialize(route, options, route_name, url_strategy)
|
167
212
|
super
|
168
|
-
@klass = Journey::Router::Utils
|
169
213
|
@required_parts = @route.required_parts
|
170
214
|
@arg_size = @required_parts.size
|
171
|
-
@optimized_path = @route.optimized_path
|
172
215
|
end
|
173
216
|
|
174
|
-
def call(t, args)
|
175
|
-
if args.size == arg_size && !
|
176
|
-
options = @options
|
177
|
-
options.merge!(t.url_options) if t.respond_to?(:url_options)
|
217
|
+
def call(t, args, inner_options)
|
218
|
+
if args.size == arg_size && !inner_options && optimize_routes_generation?(t)
|
219
|
+
options = t.url_options.merge @options
|
178
220
|
options[:path] = optimized_helper(args)
|
179
|
-
|
221
|
+
url_strategy.call options
|
180
222
|
else
|
181
223
|
super
|
182
224
|
end
|
@@ -185,18 +227,14 @@ module ActionDispatch
|
|
185
227
|
private
|
186
228
|
|
187
229
|
def optimized_helper(args)
|
188
|
-
params =
|
230
|
+
params = parameterize_args(args)
|
189
231
|
missing_keys = missing_keys(params)
|
190
232
|
|
191
233
|
unless missing_keys.empty?
|
192
234
|
raise_generation_error(params, missing_keys)
|
193
235
|
end
|
194
236
|
|
195
|
-
@
|
196
|
-
end
|
197
|
-
|
198
|
-
def replace_segment(params, segment)
|
199
|
-
Symbol === segment ? @klass.escape_segment(params[segment]) : segment
|
237
|
+
@route.format params
|
200
238
|
end
|
201
239
|
|
202
240
|
def optimize_routes_generation?(t)
|
@@ -204,7 +242,9 @@ module ActionDispatch
|
|
204
242
|
end
|
205
243
|
|
206
244
|
def parameterize_args(args)
|
207
|
-
|
245
|
+
params = {}
|
246
|
+
@required_parts.zip(args.map(&:to_param)) { |k,v| params[k] = v }
|
247
|
+
params
|
208
248
|
end
|
209
249
|
|
210
250
|
def missing_keys(args)
|
@@ -220,31 +260,66 @@ module ActionDispatch
|
|
220
260
|
end
|
221
261
|
end
|
222
262
|
|
223
|
-
def initialize(route, options)
|
263
|
+
def initialize(route, options, route_name, url_strategy)
|
224
264
|
@options = options
|
225
265
|
@segment_keys = route.segment_keys.uniq
|
226
266
|
@route = route
|
267
|
+
@url_strategy = url_strategy
|
268
|
+
@route_name = route_name
|
227
269
|
end
|
228
270
|
|
229
|
-
def call(t, args)
|
230
|
-
t.
|
231
|
-
|
271
|
+
def call(t, args, inner_options)
|
272
|
+
controller_options = t.url_options
|
273
|
+
options = controller_options.merge @options
|
274
|
+
hash = handle_positional_args(controller_options,
|
275
|
+
deprecate_string_options(inner_options) || {},
|
276
|
+
args,
|
277
|
+
options,
|
278
|
+
@segment_keys)
|
232
279
|
|
233
|
-
|
234
|
-
|
235
|
-
result = options.dup
|
280
|
+
t._routes.url_for(hash, route_name, url_strategy)
|
281
|
+
end
|
236
282
|
|
283
|
+
def handle_positional_args(controller_options, inner_options, args, result, path_params)
|
237
284
|
if args.size > 0
|
238
|
-
|
239
|
-
|
240
|
-
|
285
|
+
# take format into account
|
286
|
+
if path_params.include?(:format)
|
287
|
+
path_params_size = path_params.size - 1
|
288
|
+
else
|
289
|
+
path_params_size = path_params.size
|
290
|
+
end
|
291
|
+
|
292
|
+
if args.size < path_params_size
|
293
|
+
path_params -= controller_options.keys
|
294
|
+
path_params -= result.keys
|
241
295
|
end
|
242
|
-
|
243
|
-
|
296
|
+
path_params.each { |param|
|
297
|
+
value = inner_options.fetch(param) { args.shift }
|
298
|
+
|
299
|
+
unless param == :format && value.nil?
|
300
|
+
result[param] = value
|
301
|
+
end
|
302
|
+
}
|
244
303
|
end
|
245
304
|
|
246
305
|
result.merge!(inner_options)
|
247
306
|
end
|
307
|
+
|
308
|
+
DEPRECATED_STRING_OPTIONS = %w[controller action]
|
309
|
+
|
310
|
+
def deprecate_string_options(options)
|
311
|
+
options ||= {}
|
312
|
+
deprecated_string_options = options.keys & DEPRECATED_STRING_OPTIONS
|
313
|
+
if deprecated_string_options.any?
|
314
|
+
msg = "Calling URL helpers with string keys #{deprecated_string_options.join(", ")} is deprecated. Use symbols instead."
|
315
|
+
ActiveSupport::Deprecation.warn(msg)
|
316
|
+
deprecated_string_options.each do |option|
|
317
|
+
value = options.delete(option)
|
318
|
+
options[option.to_sym] = value
|
319
|
+
end
|
320
|
+
end
|
321
|
+
options
|
322
|
+
end
|
248
323
|
end
|
249
324
|
|
250
325
|
private
|
@@ -261,26 +336,48 @@ module ActionDispatch
|
|
261
336
|
#
|
262
337
|
# foo_url(bar, baz, bang, sort_by: 'baz')
|
263
338
|
#
|
264
|
-
def define_url_helper(route, name,
|
265
|
-
helper = UrlHelper.create(route,
|
266
|
-
|
267
|
-
@module.remove_possible_method name
|
268
|
-
@module.module_eval do
|
339
|
+
def define_url_helper(mod, route, name, opts, route_key, url_strategy)
|
340
|
+
helper = UrlHelper.create(route, opts, route_key, url_strategy)
|
341
|
+
mod.module_eval do
|
269
342
|
define_method(name) do |*args|
|
270
|
-
|
343
|
+
options = nil
|
344
|
+
options = args.pop if args.last.is_a? Hash
|
345
|
+
helper.call self, args, options
|
271
346
|
end
|
272
347
|
end
|
273
|
-
|
274
|
-
helpers << name
|
275
348
|
end
|
349
|
+
end
|
276
350
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
351
|
+
# strategy for building urls to send to the client
|
352
|
+
PATH = ->(options) { ActionDispatch::Http::URL.path_for(options) }
|
353
|
+
FULL = ->(options) { ActionDispatch::Http::URL.full_url_for(options) }
|
354
|
+
UNKNOWN = ->(options) { ActionDispatch::Http::URL.url_for(options) }
|
355
|
+
LEGACY = ->(options) {
|
356
|
+
if options.key?(:only_path)
|
357
|
+
if options[:only_path]
|
358
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
359
|
+
You are calling a `*_path` helper with the `only_path` option
|
360
|
+
explicitly set to `true`. This option will stop working on
|
361
|
+
path helpers in Rails 5. Simply remove the `only_path: true`
|
362
|
+
argument from your call as it is redundant when applied to a
|
363
|
+
path helper.
|
364
|
+
MSG
|
365
|
+
|
366
|
+
PATH.call(options)
|
367
|
+
else
|
368
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
369
|
+
You are calling a `*_path` helper with the `only_path` option
|
370
|
+
explicitly set to `false`. This option will stop working on
|
371
|
+
path helpers in Rails 5. Use the corresponding `*_url` helper
|
372
|
+
instead.
|
373
|
+
MSG
|
374
|
+
|
375
|
+
FULL.call(options)
|
376
|
+
end
|
377
|
+
else
|
378
|
+
PATH.call(options)
|
282
379
|
end
|
283
|
-
|
380
|
+
}
|
284
381
|
|
285
382
|
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
|
286
383
|
attr_accessor :disable_clear_and_finalize, :resources_path_names
|
@@ -294,7 +391,7 @@ module ActionDispatch
|
|
294
391
|
|
295
392
|
def initialize(request_class = ActionDispatch::Request)
|
296
393
|
self.named_routes = NamedRouteCollection.new
|
297
|
-
self.resources_path_names = self.class.default_resources_path_names
|
394
|
+
self.resources_path_names = self.class.default_resources_path_names
|
298
395
|
self.default_url_options = {}
|
299
396
|
self.request_class = request_class
|
300
397
|
|
@@ -304,9 +401,7 @@ module ActionDispatch
|
|
304
401
|
@finalized = false
|
305
402
|
|
306
403
|
@set = Journey::Routes.new
|
307
|
-
@router = Journey::Router.new
|
308
|
-
:parameters_key => PARAMETERS_KEY,
|
309
|
-
:request_class => request_class})
|
404
|
+
@router = Journey::Router.new @set
|
310
405
|
@formatter = Journey::Formatter.new @set
|
311
406
|
end
|
312
407
|
|
@@ -337,6 +432,7 @@ module ActionDispatch
|
|
337
432
|
mapper.instance_exec(&block)
|
338
433
|
end
|
339
434
|
end
|
435
|
+
private :eval_block
|
340
436
|
|
341
437
|
def finalize!
|
342
438
|
return if @finalized
|
@@ -352,7 +448,11 @@ module ActionDispatch
|
|
352
448
|
@prepend.each { |blk| eval_block(blk) }
|
353
449
|
end
|
354
450
|
|
355
|
-
|
451
|
+
def dispatcher(defaults)
|
452
|
+
Routing::RouteSet::Dispatcher.new(defaults)
|
453
|
+
end
|
454
|
+
|
455
|
+
module MountedHelpers
|
356
456
|
extend ActiveSupport::Concern
|
357
457
|
include UrlFor
|
358
458
|
end
|
@@ -382,40 +482,65 @@ module ActionDispatch
|
|
382
482
|
RUBY
|
383
483
|
end
|
384
484
|
|
385
|
-
def url_helpers
|
386
|
-
|
387
|
-
|
485
|
+
def url_helpers(supports_path = true)
|
486
|
+
if supports_path
|
487
|
+
@url_helpers_with_paths ||= generate_url_helpers(supports_path)
|
488
|
+
else
|
489
|
+
@url_helpers_without_paths ||= generate_url_helpers(supports_path)
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
def generate_url_helpers(supports_path)
|
494
|
+
routes = self
|
388
495
|
|
389
|
-
|
390
|
-
|
391
|
-
|
496
|
+
Module.new do
|
497
|
+
extend ActiveSupport::Concern
|
498
|
+
include UrlFor
|
499
|
+
|
500
|
+
# Define url_for in the singleton level so one can do:
|
501
|
+
# Rails.application.routes.url_helpers.url_for(args)
|
502
|
+
@_routes = routes
|
503
|
+
class << self
|
504
|
+
delegate :url_for, :optimize_routes_generation?, to: '@_routes'
|
505
|
+
attr_reader :_routes
|
506
|
+
def url_options; {}; end
|
507
|
+
end
|
392
508
|
|
393
|
-
|
394
|
-
# Rails.application.routes.url_helpers.url_for(args)
|
395
|
-
@_routes = routes
|
396
|
-
class << self
|
397
|
-
delegate :url_for, :optimize_routes_generation?, :to => '@_routes'
|
398
|
-
end
|
509
|
+
url_helpers = routes.named_routes.url_helpers_module
|
399
510
|
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
511
|
+
# Make named_routes available in the module singleton
|
512
|
+
# as well, so one can do:
|
513
|
+
# Rails.application.routes.url_helpers.posts_path
|
514
|
+
extend url_helpers
|
404
515
|
|
405
|
-
|
406
|
-
|
407
|
-
|
516
|
+
# Any class that includes this module will get all
|
517
|
+
# named routes...
|
518
|
+
include url_helpers
|
408
519
|
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
520
|
+
if supports_path
|
521
|
+
path_helpers = routes.named_routes.path_helpers_module
|
522
|
+
else
|
523
|
+
path_helpers = routes.named_routes.path_helpers_module(true)
|
524
|
+
end
|
525
|
+
|
526
|
+
include path_helpers
|
527
|
+
extend path_helpers
|
413
528
|
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
define_method(:_routes) { @_routes || routes }
|
529
|
+
# plus a singleton class method called _routes ...
|
530
|
+
included do
|
531
|
+
singleton_class.send(:redefine_method, :_routes) { routes }
|
418
532
|
end
|
533
|
+
|
534
|
+
# And an instance method _routes. Note that
|
535
|
+
# UrlFor (included in this module) add extra
|
536
|
+
# conveniences for working with @_routes.
|
537
|
+
define_method(:_routes) { @_routes || routes }
|
538
|
+
|
539
|
+
define_method(:_generate_paths_by_default) do
|
540
|
+
supports_path
|
541
|
+
end
|
542
|
+
|
543
|
+
private :_generate_paths_by_default
|
419
544
|
end
|
420
545
|
end
|
421
546
|
|
@@ -434,7 +559,9 @@ module ActionDispatch
|
|
434
559
|
"http://guides.rubyonrails.org/routing.html#restricting-the-routes-created"
|
435
560
|
end
|
436
561
|
|
437
|
-
path =
|
562
|
+
path = conditions.delete :path_info
|
563
|
+
ast = conditions.delete :parsed_path_info
|
564
|
+
path = build_path(path, ast, requirements, anchor)
|
438
565
|
conditions = build_conditions(conditions, path.names.map { |x| x.to_sym })
|
439
566
|
|
440
567
|
route = @set.add_route(app, path, conditions, defaults, name)
|
@@ -442,8 +569,9 @@ module ActionDispatch
|
|
442
569
|
route
|
443
570
|
end
|
444
571
|
|
445
|
-
def build_path(path,
|
572
|
+
def build_path(path, ast, requirements, anchor)
|
446
573
|
strexp = Journey::Router::Strexp.new(
|
574
|
+
ast,
|
447
575
|
path,
|
448
576
|
requirements,
|
449
577
|
SEPARATORS,
|
@@ -491,7 +619,7 @@ module ActionDispatch
|
|
491
619
|
end
|
492
620
|
private :build_conditions
|
493
621
|
|
494
|
-
class Generator
|
622
|
+
class Generator
|
495
623
|
PARAMETERIZE = lambda do |name, value|
|
496
624
|
if name == :controller
|
497
625
|
value
|
@@ -504,8 +632,8 @@ module ActionDispatch
|
|
504
632
|
|
505
633
|
attr_reader :options, :recall, :set, :named_route
|
506
634
|
|
507
|
-
def initialize(options, recall, set)
|
508
|
-
@named_route =
|
635
|
+
def initialize(named_route, options, recall, set)
|
636
|
+
@named_route = named_route
|
509
637
|
@options = options.dup
|
510
638
|
@recall = recall.dup
|
511
639
|
@set = set
|
@@ -596,7 +724,7 @@ module ActionDispatch
|
|
596
724
|
# Generates a path from routes, returns [path, params].
|
597
725
|
# If no route is generated the formatter will raise ActionController::UrlGenerationError
|
598
726
|
def generate
|
599
|
-
@set.formatter.generate(
|
727
|
+
@set.formatter.generate(named_route, options, recall, PARAMETERIZE)
|
600
728
|
end
|
601
729
|
|
602
730
|
def different_controller?
|
@@ -621,61 +749,74 @@ module ActionDispatch
|
|
621
749
|
end
|
622
750
|
|
623
751
|
def generate_extras(options, recall={})
|
624
|
-
|
752
|
+
route_key = options.delete :use_route
|
753
|
+
path, params = generate(route_key, options, recall)
|
625
754
|
return path, params.keys
|
626
755
|
end
|
627
756
|
|
628
|
-
def generate(options, recall = {})
|
629
|
-
Generator.new(options, recall, self).generate
|
757
|
+
def generate(route_key, options, recall = {})
|
758
|
+
Generator.new(route_key, options, recall, self).generate
|
630
759
|
end
|
760
|
+
private :generate
|
631
761
|
|
632
762
|
RESERVED_OPTIONS = [:host, :protocol, :port, :subdomain, :domain, :tld_length,
|
633
763
|
:trailing_slash, :anchor, :params, :only_path, :script_name,
|
634
764
|
:original_script_name]
|
635
765
|
|
636
|
-
def
|
637
|
-
|
766
|
+
def optimize_routes_generation?
|
767
|
+
default_url_options.empty?
|
638
768
|
end
|
639
769
|
|
640
|
-
def
|
641
|
-
|
770
|
+
def find_script_name(options)
|
771
|
+
options.delete(:script_name) || ''
|
642
772
|
end
|
643
773
|
|
644
|
-
def
|
645
|
-
|
774
|
+
def path_for(options, route_name = nil)
|
775
|
+
url_for(options, route_name, PATH)
|
646
776
|
end
|
647
777
|
|
648
|
-
# The +options+ argument must be
|
649
|
-
def url_for(options)
|
650
|
-
options = default_url_options.merge
|
778
|
+
# The +options+ argument must be a hash whose keys are *symbols*.
|
779
|
+
def url_for(options, route_name = nil, url_strategy = UNKNOWN)
|
780
|
+
options = default_url_options.merge options
|
651
781
|
|
652
|
-
user
|
653
|
-
recall = options.delete(:_recall)
|
782
|
+
user = password = nil
|
654
783
|
|
655
|
-
|
656
|
-
|
784
|
+
if options[:user] && options[:password]
|
785
|
+
user = options.delete :user
|
786
|
+
password = options.delete :password
|
787
|
+
end
|
788
|
+
|
789
|
+
recall = options.delete(:_recall) { {} }
|
790
|
+
|
791
|
+
original_script_name = options.delete(:original_script_name)
|
792
|
+
script_name = find_script_name options
|
657
793
|
|
658
|
-
if
|
794
|
+
if original_script_name
|
659
795
|
script_name = original_script_name + script_name
|
660
796
|
end
|
661
797
|
|
662
|
-
path_options = options.
|
663
|
-
|
798
|
+
path_options = options.dup
|
799
|
+
RESERVED_OPTIONS.each { |ro| path_options.delete ro }
|
664
800
|
|
665
|
-
path, params = generate(path_options, recall
|
666
|
-
|
801
|
+
path, params = generate(route_name, path_options, recall)
|
802
|
+
|
803
|
+
if options.key? :params
|
804
|
+
params.merge! options[:params]
|
805
|
+
end
|
667
806
|
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
807
|
+
options[:path] = path
|
808
|
+
options[:script_name] = script_name
|
809
|
+
options[:params] = params
|
810
|
+
options[:user] = user
|
811
|
+
options[:password] = password
|
812
|
+
|
813
|
+
url_strategy.call options
|
675
814
|
end
|
676
815
|
|
677
816
|
def call(env)
|
678
|
-
|
817
|
+
req = request_class.new(env)
|
818
|
+
req.path_info = Journey::Router::Utils.normalize_path(req.path_info)
|
819
|
+
@router.serve(req)
|
679
820
|
end
|
680
821
|
|
681
822
|
def recognize_path(path, environment = {})
|
@@ -689,8 +830,8 @@ module ActionDispatch
|
|
689
830
|
raise ActionController::RoutingError, e.message
|
690
831
|
end
|
691
832
|
|
692
|
-
req =
|
693
|
-
@router.recognize(req) do |route,
|
833
|
+
req = request_class.new(env)
|
834
|
+
@router.recognize(req) do |route, params|
|
694
835
|
params.merge!(extras)
|
695
836
|
params.each do |key, value|
|
696
837
|
if value.is_a?(String)
|
@@ -698,14 +839,12 @@ module ActionDispatch
|
|
698
839
|
params[key] = URI.parser.unescape(value)
|
699
840
|
end
|
700
841
|
end
|
701
|
-
old_params =
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
dispatcher =
|
706
|
-
end
|
842
|
+
old_params = req.path_parameters
|
843
|
+
req.path_parameters = old_params.merge params
|
844
|
+
app = route.app
|
845
|
+
if app.matches?(req) && app.dispatcher?
|
846
|
+
dispatcher = app.app
|
707
847
|
|
708
|
-
if dispatcher.is_a?(Dispatcher)
|
709
848
|
if dispatcher.controller(params, false)
|
710
849
|
dispatcher.prepare_params!(params)
|
711
850
|
return params
|
@@ -717,17 +856,7 @@ module ActionDispatch
|
|
717
856
|
|
718
857
|
raise ActionController::RoutingError, "No route matches #{path.inspect}"
|
719
858
|
end
|
720
|
-
|
721
|
-
private
|
722
|
-
|
723
|
-
def extract_authentication(options)
|
724
|
-
if options[:user] && options[:password]
|
725
|
-
[options.delete(:user), options.delete(:password)]
|
726
|
-
else
|
727
|
-
nil
|
728
|
-
end
|
729
|
-
end
|
730
|
-
|
731
859
|
end
|
860
|
+
# :startdoc:
|
732
861
|
end
|
733
862
|
end
|