actionpack 4.1.7 → 4.2.11
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 +5 -5
- data/CHANGELOG.md +404 -451
- 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/rendering.rb +7 -1
- data/lib/abstract_controller/url_for.rb +1 -1
- data/lib/action_controller/base.rb +3 -2
- 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 +20 -10
- 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 +25 -246
- data/lib/action_controller/metal/params_wrapper.rb +5 -5
- 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 +29 -11
- 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 +129 -14
- 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 +119 -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 +18 -4
- 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 +74 -23
- data/lib/action_dispatch/http/upload.rb +9 -8
- data/lib/action_dispatch/http/url.rb +89 -70
- data/lib/action_dispatch/journey/formatter.rb +34 -18
- 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 +4 -19
- data/lib/action_dispatch/journey/router/strexp.rb +9 -6
- data/lib/action_dispatch/journey/router/utils.rb +1 -1
- data/lib/action_dispatch/journey/router.rb +53 -77
- data/lib/action_dispatch/journey/routes.rb +4 -0
- 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 +34 -34
- 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/ssl.rb +1 -1
- data/lib/action_dispatch/middleware/static.rb +75 -39
- 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/railtie.rb +2 -0
- 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 +414 -283
- 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 +300 -173
- data/lib/action_dispatch/routing/routes_proxy.rb +5 -4
- data/lib/action_dispatch/routing/url_for.rb +17 -5
- 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 +28 -20
- data/lib/action_dispatch/testing/test_request.rb +1 -1
- data/lib/action_dispatch/testing/test_response.rb +1 -5
- 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,
|
@@ -1,44 +1,37 @@
|
|
1
1
|
require 'action_dispatch/journey'
|
2
2
|
require 'forwardable'
|
3
|
-
require 'thread_safe'
|
4
3
|
require 'active_support/concern'
|
5
4
|
require 'active_support/core_ext/object/to_query'
|
6
5
|
require 'active_support/core_ext/hash/slice'
|
7
6
|
require 'active_support/core_ext/module/remove_method'
|
8
7
|
require 'active_support/core_ext/array/extract_options'
|
8
|
+
require 'active_support/core_ext/string/filters'
|
9
9
|
require 'action_controller/metal/exceptions'
|
10
10
|
require 'action_dispatch/http/request'
|
11
|
+
require 'action_dispatch/routing/endpoint'
|
11
12
|
|
12
13
|
module ActionDispatch
|
13
14
|
module Routing
|
14
|
-
|
15
|
+
# :stopdoc:
|
16
|
+
class RouteSet
|
15
17
|
# Since the router holds references to many parts of the system
|
16
18
|
# like engines, controllers and the application itself, inspecting
|
17
19
|
# the route set can actually be really slow, therefore we default
|
18
20
|
# alias inspect to to_s.
|
19
21
|
alias inspect to_s
|
20
22
|
|
21
|
-
|
23
|
+
mattr_accessor :relative_url_root
|
22
24
|
|
23
|
-
class Dispatcher
|
24
|
-
def initialize(
|
25
|
-
@defaults =
|
26
|
-
@glob_param = options.delete(:glob)
|
27
|
-
@controller_class_names = ThreadSafe::Cache.new
|
25
|
+
class Dispatcher < Routing::Endpoint
|
26
|
+
def initialize(defaults)
|
27
|
+
@defaults = defaults
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
31
|
-
params = env[PARAMETERS_KEY]
|
30
|
+
def dispatcher?; true; end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
params
|
36
|
-
next unless value.respond_to?(:valid_encoding?)
|
37
|
-
|
38
|
-
unless value.valid_encoding?
|
39
|
-
raise ActionController::BadRequest, "Invalid parameter: #{key} => #{value}"
|
40
|
-
end
|
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)
|
@@ -74,7 +66,7 @@ module ActionDispatch
|
|
74
66
|
private
|
75
67
|
|
76
68
|
def controller_reference(controller_param)
|
77
|
-
const_name =
|
69
|
+
const_name = "#{controller_param.camelize}Controller"
|
78
70
|
ActiveSupport::Dependencies.constantize(const_name)
|
79
71
|
end
|
80
72
|
|
@@ -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)
|
@@ -212,7 +252,7 @@ module ActionDispatch
|
|
212
252
|
end
|
213
253
|
|
214
254
|
def raise_generation_error(args, missing_keys)
|
215
|
-
constraints = Hash[@route.requirements.merge(args).
|
255
|
+
constraints = Hash[@route.requirements.merge(args).sort_by{|k,v| k.to_s}]
|
216
256
|
message = "No route matches #{constraints.inspect}"
|
217
257
|
message << " missing required keys: #{missing_keys.sort.inspect}"
|
218
258
|
|
@@ -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
|
241
290
|
end
|
242
|
-
|
243
|
-
|
291
|
+
|
292
|
+
if args.size < path_params_size
|
293
|
+
path_params -= controller_options.keys
|
294
|
+
path_params -= result.keys
|
295
|
+
end
|
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
|
@@ -369,9 +469,11 @@ module ActionDispatch
|
|
369
469
|
return if MountedHelpers.method_defined?(name)
|
370
470
|
|
371
471
|
routes = self
|
472
|
+
helpers = routes.url_helpers
|
473
|
+
|
372
474
|
MountedHelpers.class_eval do
|
373
475
|
define_method "_#{name}" do
|
374
|
-
RoutesProxy.new(routes, _routes_context)
|
476
|
+
RoutesProxy.new(routes, _routes_context, helpers)
|
375
477
|
end
|
376
478
|
end
|
377
479
|
|
@@ -382,40 +484,57 @@ module ActionDispatch
|
|
382
484
|
RUBY
|
383
485
|
end
|
384
486
|
|
385
|
-
def url_helpers
|
386
|
-
|
387
|
-
routes = self
|
487
|
+
def url_helpers(supports_path = true)
|
488
|
+
routes = self
|
388
489
|
|
389
|
-
|
390
|
-
|
391
|
-
|
490
|
+
Module.new do
|
491
|
+
extend ActiveSupport::Concern
|
492
|
+
include UrlFor
|
493
|
+
|
494
|
+
# Define url_for in the singleton level so one can do:
|
495
|
+
# Rails.application.routes.url_helpers.url_for(args)
|
496
|
+
@_routes = routes
|
497
|
+
class << self
|
498
|
+
delegate :url_for, :optimize_routes_generation?, to: '@_routes'
|
499
|
+
attr_reader :_routes
|
500
|
+
def url_options; {}; end
|
501
|
+
end
|
392
502
|
|
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
|
503
|
+
url_helpers = routes.named_routes.url_helpers_module
|
399
504
|
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
505
|
+
# Make named_routes available in the module singleton
|
506
|
+
# as well, so one can do:
|
507
|
+
# Rails.application.routes.url_helpers.posts_path
|
508
|
+
extend url_helpers
|
404
509
|
|
405
|
-
|
406
|
-
|
407
|
-
|
510
|
+
# Any class that includes this module will get all
|
511
|
+
# named routes...
|
512
|
+
include url_helpers
|
408
513
|
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
514
|
+
if supports_path
|
515
|
+
path_helpers = routes.named_routes.path_helpers_module
|
516
|
+
else
|
517
|
+
path_helpers = routes.named_routes.path_helpers_module(true)
|
518
|
+
end
|
519
|
+
|
520
|
+
include path_helpers
|
521
|
+
extend path_helpers
|
413
522
|
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
define_method(:_routes) { @_routes || routes }
|
523
|
+
# plus a singleton class method called _routes ...
|
524
|
+
included do
|
525
|
+
singleton_class.send(:redefine_method, :_routes) { routes }
|
418
526
|
end
|
527
|
+
|
528
|
+
# And an instance method _routes. Note that
|
529
|
+
# UrlFor (included in this module) add extra
|
530
|
+
# conveniences for working with @_routes.
|
531
|
+
define_method(:_routes) { @_routes || routes }
|
532
|
+
|
533
|
+
define_method(:_generate_paths_by_default) do
|
534
|
+
supports_path
|
535
|
+
end
|
536
|
+
|
537
|
+
private :_generate_paths_by_default
|
419
538
|
end
|
420
539
|
end
|
421
540
|
|
@@ -434,7 +553,9 @@ module ActionDispatch
|
|
434
553
|
"http://guides.rubyonrails.org/routing.html#restricting-the-routes-created"
|
435
554
|
end
|
436
555
|
|
437
|
-
path =
|
556
|
+
path = conditions.delete :path_info
|
557
|
+
ast = conditions.delete :parsed_path_info
|
558
|
+
path = build_path(path, ast, requirements, anchor)
|
438
559
|
conditions = build_conditions(conditions, path.names.map { |x| x.to_sym })
|
439
560
|
|
440
561
|
route = @set.add_route(app, path, conditions, defaults, name)
|
@@ -442,8 +563,9 @@ module ActionDispatch
|
|
442
563
|
route
|
443
564
|
end
|
444
565
|
|
445
|
-
def build_path(path,
|
566
|
+
def build_path(path, ast, requirements, anchor)
|
446
567
|
strexp = Journey::Router::Strexp.new(
|
568
|
+
ast,
|
447
569
|
path,
|
448
570
|
requirements,
|
449
571
|
SEPARATORS,
|
@@ -491,7 +613,7 @@ module ActionDispatch
|
|
491
613
|
end
|
492
614
|
private :build_conditions
|
493
615
|
|
494
|
-
class Generator
|
616
|
+
class Generator
|
495
617
|
PARAMETERIZE = lambda do |name, value|
|
496
618
|
if name == :controller
|
497
619
|
value
|
@@ -504,8 +626,8 @@ module ActionDispatch
|
|
504
626
|
|
505
627
|
attr_reader :options, :recall, :set, :named_route
|
506
628
|
|
507
|
-
def initialize(options, recall, set)
|
508
|
-
@named_route =
|
629
|
+
def initialize(named_route, options, recall, set)
|
630
|
+
@named_route = named_route
|
509
631
|
@options = options.dup
|
510
632
|
@recall = recall.dup
|
511
633
|
@set = set
|
@@ -596,7 +718,7 @@ module ActionDispatch
|
|
596
718
|
# Generates a path from routes, returns [path, params].
|
597
719
|
# If no route is generated the formatter will raise ActionController::UrlGenerationError
|
598
720
|
def generate
|
599
|
-
@set.formatter.generate(
|
721
|
+
@set.formatter.generate(named_route, options, recall, PARAMETERIZE)
|
600
722
|
end
|
601
723
|
|
602
724
|
def different_controller?
|
@@ -621,61 +743,78 @@ module ActionDispatch
|
|
621
743
|
end
|
622
744
|
|
623
745
|
def generate_extras(options, recall={})
|
624
|
-
|
746
|
+
route_key = options.delete :use_route
|
747
|
+
path, params = generate(route_key, options, recall)
|
625
748
|
return path, params.keys
|
626
749
|
end
|
627
750
|
|
628
|
-
def generate(options, recall = {})
|
629
|
-
Generator.new(options, recall, self).generate
|
751
|
+
def generate(route_key, options, recall = {})
|
752
|
+
Generator.new(route_key, options, recall, self).generate
|
630
753
|
end
|
754
|
+
private :generate
|
631
755
|
|
632
756
|
RESERVED_OPTIONS = [:host, :protocol, :port, :subdomain, :domain, :tld_length,
|
633
757
|
:trailing_slash, :anchor, :params, :only_path, :script_name,
|
634
|
-
:original_script_name]
|
758
|
+
:original_script_name, :relative_url_root]
|
635
759
|
|
636
|
-
def
|
637
|
-
|
760
|
+
def optimize_routes_generation?
|
761
|
+
default_url_options.empty?
|
638
762
|
end
|
639
763
|
|
640
|
-
def
|
641
|
-
|
764
|
+
def find_script_name(options)
|
765
|
+
options.delete(:script_name) || find_relative_url_root(options) || ''
|
642
766
|
end
|
643
767
|
|
644
|
-
def
|
645
|
-
|
768
|
+
def find_relative_url_root(options)
|
769
|
+
options.delete(:relative_url_root) || relative_url_root
|
770
|
+
end
|
771
|
+
|
772
|
+
def path_for(options, route_name = nil)
|
773
|
+
url_for(options, route_name, PATH)
|
646
774
|
end
|
647
775
|
|
648
|
-
# The +options+ argument must be
|
649
|
-
def url_for(options)
|
650
|
-
options = default_url_options.merge
|
776
|
+
# The +options+ argument must be a hash whose keys are *symbols*.
|
777
|
+
def url_for(options, route_name = nil, url_strategy = UNKNOWN)
|
778
|
+
options = default_url_options.merge options
|
651
779
|
|
652
|
-
user
|
653
|
-
recall = options.delete(:_recall)
|
780
|
+
user = password = nil
|
654
781
|
|
655
|
-
|
656
|
-
|
782
|
+
if options[:user] && options[:password]
|
783
|
+
user = options.delete :user
|
784
|
+
password = options.delete :password
|
785
|
+
end
|
786
|
+
|
787
|
+
recall = options.delete(:_recall) { {} }
|
788
|
+
|
789
|
+
original_script_name = options.delete(:original_script_name)
|
790
|
+
script_name = find_script_name options
|
657
791
|
|
658
|
-
if
|
792
|
+
if original_script_name
|
659
793
|
script_name = original_script_name + script_name
|
660
794
|
end
|
661
795
|
|
662
|
-
path_options = options.
|
663
|
-
|
796
|
+
path_options = options.dup
|
797
|
+
RESERVED_OPTIONS.each { |ro| path_options.delete ro }
|
664
798
|
|
665
|
-
path, params = generate(path_options, recall
|
666
|
-
|
799
|
+
path, params = generate(route_name, path_options, recall)
|
800
|
+
|
801
|
+
if options.key? :params
|
802
|
+
params.merge! options[:params]
|
803
|
+
end
|
667
804
|
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
805
|
+
options[:path] = path
|
806
|
+
options[:script_name] = script_name
|
807
|
+
options[:params] = params
|
808
|
+
options[:user] = user
|
809
|
+
options[:password] = password
|
810
|
+
|
811
|
+
url_strategy.call options
|
675
812
|
end
|
676
813
|
|
677
814
|
def call(env)
|
678
|
-
|
815
|
+
req = request_class.new(env)
|
816
|
+
req.path_info = Journey::Router::Utils.normalize_path(req.path_info)
|
817
|
+
@router.serve(req)
|
679
818
|
end
|
680
819
|
|
681
820
|
def recognize_path(path, environment = {})
|
@@ -689,8 +828,8 @@ module ActionDispatch
|
|
689
828
|
raise ActionController::RoutingError, e.message
|
690
829
|
end
|
691
830
|
|
692
|
-
req =
|
693
|
-
@router.recognize(req) do |route,
|
831
|
+
req = request_class.new(env)
|
832
|
+
@router.recognize(req) do |route, params|
|
694
833
|
params.merge!(extras)
|
695
834
|
params.each do |key, value|
|
696
835
|
if value.is_a?(String)
|
@@ -698,14 +837,12 @@ module ActionDispatch
|
|
698
837
|
params[key] = URI.parser.unescape(value)
|
699
838
|
end
|
700
839
|
end
|
701
|
-
old_params =
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
dispatcher =
|
706
|
-
end
|
840
|
+
old_params = req.path_parameters
|
841
|
+
req.path_parameters = old_params.merge params
|
842
|
+
app = route.app
|
843
|
+
if app.matches?(req) && app.dispatcher?
|
844
|
+
dispatcher = app.app
|
707
845
|
|
708
|
-
if dispatcher.is_a?(Dispatcher)
|
709
846
|
if dispatcher.controller(params, false)
|
710
847
|
dispatcher.prepare_params!(params)
|
711
848
|
return params
|
@@ -717,17 +854,7 @@ module ActionDispatch
|
|
717
854
|
|
718
855
|
raise ActionController::RoutingError, "No route matches #{path.inspect}"
|
719
856
|
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
857
|
end
|
858
|
+
# :startdoc:
|
732
859
|
end
|
733
860
|
end
|