actionpack 3.1.12 → 3.2.0.rc1
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.
- data/CHANGELOG.md +5503 -108
- data/README.rdoc +3 -3
- data/lib/abstract_controller/asset_paths.rb +1 -1
- data/lib/abstract_controller/base.rb +1 -1
- data/lib/abstract_controller/callbacks.rb +102 -18
- data/lib/abstract_controller/helpers.rb +1 -1
- data/lib/abstract_controller/layouts.rb +116 -50
- data/lib/abstract_controller/logger.rb +1 -1
- data/lib/abstract_controller/railties/routes_helpers.rb +2 -2
- data/lib/abstract_controller/rendering.rb +1 -6
- data/lib/abstract_controller/view_paths.rb +6 -5
- data/lib/action_controller.rb +0 -15
- data/lib/action_controller/caching.rb +0 -1
- data/lib/action_controller/caching/actions.rb +5 -6
- data/lib/action_controller/caching/fragments.rb +18 -18
- data/lib/action_controller/caching/pages.rb +7 -6
- data/lib/action_controller/caching/sweeping.rb +1 -1
- data/lib/action_controller/log_subscriber.rb +8 -4
- data/lib/action_controller/metal.rb +7 -1
- data/lib/action_controller/metal/conditional_get.rb +49 -4
- data/lib/action_controller/metal/data_streaming.rb +17 -5
- data/lib/action_controller/metal/force_ssl.rb +8 -5
- data/lib/action_controller/metal/helpers.rb +7 -4
- data/lib/action_controller/metal/http_authentication.rb +9 -12
- data/lib/action_controller/metal/instrumentation.rb +9 -4
- data/lib/action_controller/metal/mime_responds.rb +4 -4
- data/lib/action_controller/metal/params_wrapper.rb +12 -8
- data/lib/action_controller/metal/redirecting.rb +7 -6
- data/lib/action_controller/metal/renderers.rb +9 -11
- data/lib/action_controller/metal/request_forgery_protection.rb +2 -1
- data/lib/action_controller/metal/rescue.rb +13 -0
- data/lib/action_controller/metal/responder.rb +11 -23
- data/lib/action_controller/metal/streaming.rb +0 -25
- data/lib/action_controller/railtie.rb +1 -0
- data/lib/action_controller/railties/paths.rb +4 -3
- data/lib/action_controller/record_identifier.rb +4 -4
- data/lib/action_controller/test_case.rb +60 -56
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +6 -6
- data/lib/action_dispatch.rb +5 -1
- data/lib/action_dispatch/http/cache.rb +27 -15
- data/lib/action_dispatch/http/filter_parameters.rb +3 -1
- data/lib/action_dispatch/http/headers.rb +3 -5
- data/lib/action_dispatch/http/mime_negotiation.rb +2 -1
- data/lib/action_dispatch/http/mime_type.rb +7 -3
- data/lib/action_dispatch/http/mime_types.rb +12 -0
- data/lib/action_dispatch/http/parameter_filter.rb +3 -1
- data/lib/action_dispatch/http/parameters.rb +0 -4
- data/lib/action_dispatch/http/request.rb +18 -68
- data/lib/action_dispatch/http/response.rb +11 -32
- data/lib/action_dispatch/http/upload.rb +3 -14
- data/lib/action_dispatch/http/url.rb +1 -1
- data/lib/action_dispatch/middleware/callbacks.rb +1 -2
- data/lib/action_dispatch/middleware/cookies.rb +20 -16
- data/lib/action_dispatch/middleware/debug_exceptions.rb +82 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +78 -0
- data/lib/action_dispatch/middleware/flash.rb +6 -9
- data/lib/action_dispatch/middleware/params_parser.rb +6 -11
- data/lib/action_dispatch/middleware/public_exceptions.rb +30 -0
- data/lib/action_dispatch/middleware/reloader.rb +38 -14
- data/lib/action_dispatch/middleware/remote_ip.rb +66 -36
- data/lib/action_dispatch/middleware/request_id.rb +39 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +4 -16
- data/lib/action_dispatch/middleware/session/cache_store.rb +50 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +1 -1
- data/lib/action_dispatch/middleware/show_exceptions.rb +58 -142
- data/lib/action_dispatch/middleware/static.rb +2 -10
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +13 -8
- data/lib/action_dispatch/railtie.rb +15 -1
- data/lib/action_dispatch/routing.rb +1 -2
- data/lib/action_dispatch/routing/mapper.rb +108 -107
- data/lib/action_dispatch/routing/redirection.rb +63 -69
- data/lib/action_dispatch/routing/route_set.rb +75 -43
- data/lib/action_dispatch/routing/routes_proxy.rb +0 -4
- data/lib/action_dispatch/routing/url_for.rb +3 -3
- data/lib/action_dispatch/testing/assertions/response.rb +5 -7
- data/lib/action_dispatch/testing/assertions/routing.rb +10 -9
- data/lib/action_dispatch/testing/integration.rb +8 -25
- data/lib/action_dispatch/testing/test_process.rb +3 -2
- data/lib/action_dispatch/testing/test_request.rb +4 -23
- data/lib/action_pack/version.rb +3 -3
- data/lib/action_view.rb +1 -5
- data/lib/action_view/asset_paths.rb +7 -8
- data/lib/action_view/base.rb +7 -5
- data/lib/action_view/helpers/asset_paths.rb +1 -1
- data/lib/action_view/helpers/asset_tag_helper.rb +4 -8
- data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +3 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
- data/lib/action_view/helpers/capture_helper.rb +3 -3
- data/lib/action_view/helpers/controller_helper.rb +1 -1
- data/lib/action_view/helpers/date_helper.rb +26 -18
- data/lib/action_view/helpers/debug_helper.rb +1 -1
- data/lib/action_view/helpers/form_helper.rb +71 -13
- data/lib/action_view/helpers/form_options_helper.rb +65 -34
- data/lib/action_view/helpers/form_tag_helper.rb +24 -18
- data/lib/action_view/helpers/javascript_helper.rb +12 -3
- data/lib/action_view/helpers/number_helper.rb +3 -2
- data/lib/action_view/helpers/record_tag_helper.rb +51 -5
- data/lib/action_view/helpers/rendering_helper.rb +2 -2
- data/lib/action_view/helpers/sanitize_helper.rb +6 -7
- data/lib/action_view/helpers/tag_helper.rb +1 -1
- data/lib/action_view/helpers/text_helper.rb +5 -4
- data/lib/action_view/helpers/url_helper.rb +19 -11
- data/lib/action_view/locale/en.yml +6 -0
- data/lib/action_view/log_subscriber.rb +1 -1
- data/lib/action_view/lookup_context.rb +123 -125
- data/lib/action_view/path_set.rb +60 -13
- data/lib/action_view/renderer/abstract_renderer.rb +16 -11
- data/lib/action_view/renderer/partial_renderer.rb +59 -40
- data/lib/action_view/renderer/template_renderer.rb +29 -17
- data/lib/action_view/template.rb +0 -1
- data/lib/action_view/template/error.rb +6 -5
- data/lib/action_view/template/handlers.rb +0 -6
- data/lib/action_view/template/handlers/builder.rb +10 -1
- data/lib/action_view/template/handlers/erb.rb +2 -2
- data/lib/action_view/template/resolver.rb +20 -31
- data/lib/action_view/test_case.rb +7 -10
- data/lib/sprockets/assets.rake +1 -1
- data/lib/sprockets/bootstrap.rb +3 -31
- data/lib/sprockets/compressors.rb +69 -7
- data/lib/sprockets/helpers/rails_helper.rb +6 -11
- data/lib/sprockets/railtie.rb +1 -0
- data/lib/sprockets/static_compiler.rb +0 -3
- metadata +57 -86
- checksums.yaml +0 -7
- data/lib/action_dispatch/middleware/closed_error.rb +0 -7
- data/lib/action_dispatch/routing/route.rb +0 -67
- data/lib/action_view/template/handler.rb +0 -49
@@ -1,9 +1,55 @@
|
|
1
1
|
require 'action_dispatch/http/request'
|
2
|
-
require 'active_support/core_ext/uri'
|
3
|
-
require 'rack/utils'
|
4
2
|
|
5
3
|
module ActionDispatch
|
6
4
|
module Routing
|
5
|
+
class Redirect # :nodoc:
|
6
|
+
attr_reader :status, :block
|
7
|
+
|
8
|
+
def initialize(status, block)
|
9
|
+
@status = status
|
10
|
+
@block = block
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
req = Request.new(env)
|
15
|
+
|
16
|
+
uri = URI.parse(path(req.symbolized_path_parameters, req))
|
17
|
+
uri.scheme ||= req.scheme
|
18
|
+
uri.host ||= req.host
|
19
|
+
uri.port ||= req.port unless req.standard_port?
|
20
|
+
|
21
|
+
body = %(<html><body>You are being <a href="#{ERB::Util.h(uri.to_s)}">redirected</a>.</body></html>)
|
22
|
+
|
23
|
+
headers = {
|
24
|
+
'Location' => uri.to_s,
|
25
|
+
'Content-Type' => 'text/html',
|
26
|
+
'Content-Length' => body.length.to_s
|
27
|
+
}
|
28
|
+
|
29
|
+
[ status, headers, [body] ]
|
30
|
+
end
|
31
|
+
|
32
|
+
def path(params, request)
|
33
|
+
block.call params, request
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class OptionRedirect < Redirect # :nodoc:
|
38
|
+
alias :options :block
|
39
|
+
|
40
|
+
def path(params, request)
|
41
|
+
url_options = {
|
42
|
+
:protocol => request.protocol,
|
43
|
+
:host => request.host,
|
44
|
+
:port => request.optional_port,
|
45
|
+
:path => request.path,
|
46
|
+
:params => request.query_parameters
|
47
|
+
}.merge options
|
48
|
+
|
49
|
+
ActionDispatch::Http::URL.url_for url_options
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
7
53
|
module Redirection
|
8
54
|
|
9
55
|
# Redirect any path to another path:
|
@@ -42,79 +88,27 @@ module ActionDispatch
|
|
42
88
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
43
89
|
status = options.delete(:status) || 301
|
44
90
|
|
45
|
-
|
46
|
-
|
47
|
-
path_proc = if path.is_a?(String)
|
48
|
-
proc { |params| (params.empty? || !path.match(/%\{\w*\}/)) ? path : (path % escape(params)) }
|
49
|
-
elsif options.any?
|
50
|
-
options_proc(options)
|
51
|
-
elsif path.respond_to?(:call)
|
52
|
-
proc { |params, request| path.call(params, request) }
|
53
|
-
elsif block
|
54
|
-
block
|
55
|
-
else
|
56
|
-
raise ArgumentError, "redirection argument not supported"
|
57
|
-
end
|
58
|
-
|
59
|
-
redirection_proc(status, path_proc)
|
60
|
-
end
|
61
|
-
|
62
|
-
private
|
63
|
-
|
64
|
-
def options_proc(options)
|
65
|
-
proc do |params, request|
|
66
|
-
path = if options[:path].nil?
|
67
|
-
request.path
|
68
|
-
elsif params.empty? || !options[:path].match(/%\{\w*\}/)
|
69
|
-
options.delete(:path)
|
70
|
-
else
|
71
|
-
(options.delete(:path) % escape_path(params))
|
72
|
-
end
|
73
|
-
|
74
|
-
default_options = {
|
75
|
-
:protocol => request.protocol,
|
76
|
-
:host => request.host,
|
77
|
-
:port => request.optional_port,
|
78
|
-
:path => path,
|
79
|
-
:params => request.query_parameters
|
80
|
-
}
|
81
|
-
|
82
|
-
ActionDispatch::Http::URL.url_for(options.reverse_merge(default_options))
|
83
|
-
end
|
84
|
-
end
|
91
|
+
return OptionRedirect.new(status, options) if options.any?
|
85
92
|
|
86
|
-
|
87
|
-
lambda do |env|
|
88
|
-
req = Request.new(env)
|
89
|
-
|
90
|
-
params = [req.symbolized_path_parameters]
|
91
|
-
params << req if path_proc.arity > 1
|
92
|
-
|
93
|
-
uri = URI.parse(path_proc.call(*params))
|
94
|
-
uri.scheme ||= req.scheme
|
95
|
-
uri.host ||= req.host
|
96
|
-
uri.port ||= req.port unless req.standard_port?
|
93
|
+
path = args.shift
|
97
94
|
|
98
|
-
|
95
|
+
block = lambda { |params, request|
|
96
|
+
(params.empty? || !path.match(/%\{\w*\}/)) ? path : (path % params)
|
97
|
+
} if String === path
|
99
98
|
|
100
|
-
|
101
|
-
'Location' => uri.to_s,
|
102
|
-
'Content-Type' => 'text/html',
|
103
|
-
'Content-Length' => body.length.to_s
|
104
|
-
}
|
99
|
+
block = path if path.respond_to? :call
|
105
100
|
|
106
|
-
|
107
|
-
|
101
|
+
# :FIXME: remove in Rails 4.0
|
102
|
+
if block && block.respond_to?(:arity) && block.arity < 2
|
103
|
+
msg = "redirect blocks with arity of #{block.arity} are deprecated. Your block must take 2 parameters: the environment, and a request object"
|
104
|
+
ActiveSupport::Deprecation.warn msg
|
105
|
+
block = lambda { |params, _| block.call(params) }
|
108
106
|
end
|
109
107
|
|
110
|
-
|
111
|
-
Hash[params.map{ |k,v| [k, Rack::Utils.escape(v)] }]
|
112
|
-
end
|
113
|
-
|
114
|
-
def escape_path(params)
|
115
|
-
Hash[params.map{ |k,v| [k, URI.parser.escape(v)] }]
|
116
|
-
end
|
108
|
+
raise ArgumentError, "redirection argument not supported" unless block
|
117
109
|
|
110
|
+
Redirect.new status, block
|
111
|
+
end
|
118
112
|
end
|
119
113
|
end
|
120
|
-
end
|
114
|
+
end
|
@@ -1,19 +1,14 @@
|
|
1
|
-
require '
|
1
|
+
require 'journey'
|
2
2
|
require 'forwardable'
|
3
3
|
require 'active_support/core_ext/object/blank'
|
4
4
|
require 'active_support/core_ext/object/to_query'
|
5
5
|
require 'active_support/core_ext/hash/slice'
|
6
6
|
require 'active_support/core_ext/module/remove_method'
|
7
|
+
require 'action_controller/metal/exceptions'
|
7
8
|
|
8
9
|
module ActionDispatch
|
9
10
|
module Routing
|
10
11
|
class RouteSet #:nodoc:
|
11
|
-
# Since the router holds references to many parts of the system
|
12
|
-
# like engines, controllers and the application itself, inspecting
|
13
|
-
# the route set can actually be really slow, therefore we default
|
14
|
-
# alias inspect to to_s.
|
15
|
-
alias inspect to_s
|
16
|
-
|
17
12
|
PARAMETERS_KEY = 'action_dispatch.request.path_parameters'
|
18
13
|
|
19
14
|
class Dispatcher #:nodoc:
|
@@ -42,7 +37,7 @@ module ActionDispatch
|
|
42
37
|
|
43
38
|
# If this is a default_controller (i.e. a controller specified by the user)
|
44
39
|
# we should raise an error in case it's not found, because it usually means
|
45
|
-
#
|
40
|
+
# a user error. However, if the controller was retrieved through a dynamic
|
46
41
|
# segment, as in :controller(/:action), we should simply return nil and
|
47
42
|
# delegate the control back to Rack cascade. Besides, if this is not a default
|
48
43
|
# controller, it means we should respect the @scope[:module] parameter.
|
@@ -172,7 +167,7 @@ module ActionDispatch
|
|
172
167
|
options = args.extract_options!
|
173
168
|
result = #{options.inspect}
|
174
169
|
|
175
|
-
if args.
|
170
|
+
if args.any?
|
176
171
|
result[:_positional_args] = args
|
177
172
|
result[:_positional_keys] = #{route.segment_keys.inspect}
|
178
173
|
end
|
@@ -211,29 +206,42 @@ module ActionDispatch
|
|
211
206
|
end
|
212
207
|
end
|
213
208
|
|
214
|
-
attr_accessor :
|
209
|
+
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
|
215
210
|
attr_accessor :disable_clear_and_finalize, :resources_path_names
|
216
211
|
attr_accessor :default_url_options, :request_class, :valid_conditions
|
217
212
|
|
213
|
+
alias :routes :set
|
214
|
+
|
218
215
|
def self.default_resources_path_names
|
219
216
|
{ :new => 'new', :edit => 'edit' }
|
220
217
|
end
|
221
218
|
|
222
219
|
def initialize(request_class = ActionDispatch::Request)
|
223
|
-
self.routes = []
|
224
220
|
self.named_routes = NamedRouteCollection.new
|
225
221
|
self.resources_path_names = self.class.default_resources_path_names.dup
|
226
222
|
self.default_url_options = {}
|
227
223
|
|
228
224
|
self.request_class = request_class
|
229
|
-
|
225
|
+
@valid_conditions = {}
|
226
|
+
|
227
|
+
request_class.public_instance_methods.each { |m|
|
228
|
+
@valid_conditions[m.to_sym] = true
|
229
|
+
}
|
230
|
+
@valid_conditions[:controller] = true
|
231
|
+
@valid_conditions[:action] = true
|
232
|
+
|
230
233
|
self.valid_conditions.delete(:id)
|
231
|
-
self.valid_conditions.push(:controller, :action)
|
232
234
|
|
233
|
-
@append
|
234
|
-
@prepend
|
235
|
+
@append = []
|
236
|
+
@prepend = []
|
235
237
|
@disable_clear_and_finalize = false
|
236
|
-
|
238
|
+
@finalized = false
|
239
|
+
|
240
|
+
@set = Journey::Routes.new
|
241
|
+
@router = Journey::Router.new(@set, {
|
242
|
+
:parameters_key => PARAMETERS_KEY,
|
243
|
+
:request_class => request_class})
|
244
|
+
@formatter = Journey::Formatter.new @set
|
237
245
|
end
|
238
246
|
|
239
247
|
def draw(&block)
|
@@ -269,17 +277,13 @@ module ActionDispatch
|
|
269
277
|
return if @finalized
|
270
278
|
@append.each { |blk| eval_block(blk) }
|
271
279
|
@finalized = true
|
272
|
-
@set.freeze
|
273
280
|
end
|
274
281
|
|
275
282
|
def clear!
|
276
283
|
@finalized = false
|
277
|
-
routes.clear
|
278
284
|
named_routes.clear
|
279
|
-
|
280
|
-
|
281
|
-
:request_class => request_class
|
282
|
-
)
|
285
|
+
set.clear
|
286
|
+
formatter.clear
|
283
287
|
@prepend.each { |blk| eval_block(blk) }
|
284
288
|
end
|
285
289
|
|
@@ -347,26 +351,54 @@ module ActionDispatch
|
|
347
351
|
|
348
352
|
def add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil, anchor = true)
|
349
353
|
raise ArgumentError, "Invalid route name: '#{name}'" unless name.blank? || name.to_s.match(/^[_a-z]\w*$/i)
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
+
|
355
|
+
path = build_path(conditions.delete(:path_info), requirements, SEPARATORS, anchor)
|
356
|
+
conditions = build_conditions(conditions, valid_conditions, path.names.map { |x| x.to_sym })
|
357
|
+
|
358
|
+
route = @set.add_route(app, path, conditions, defaults, name)
|
359
|
+
named_routes[name] = route if name && !named_routes[name]
|
354
360
|
route
|
355
361
|
end
|
356
362
|
|
363
|
+
def build_path(path, requirements, separators, anchor)
|
364
|
+
strexp = Journey::Router::Strexp.new(
|
365
|
+
path,
|
366
|
+
requirements,
|
367
|
+
SEPARATORS,
|
368
|
+
anchor)
|
369
|
+
|
370
|
+
Journey::Path::Pattern.new(strexp)
|
371
|
+
end
|
372
|
+
private :build_path
|
373
|
+
|
374
|
+
def build_conditions(current_conditions, req_predicates, path_values)
|
375
|
+
conditions = current_conditions.dup
|
376
|
+
|
377
|
+
verbs = conditions[:request_method] || []
|
378
|
+
|
379
|
+
# Rack-Mount requires that :request_method be a regular expression.
|
380
|
+
# :request_method represents the HTTP verb that matches this route.
|
381
|
+
#
|
382
|
+
# Here we munge values before they get sent on to rack-mount.
|
383
|
+
unless verbs.empty?
|
384
|
+
conditions[:request_method] = %r[^#{verbs.join('|')}$]
|
385
|
+
end
|
386
|
+
conditions.delete_if { |k,v| !(req_predicates.include?(k) || path_values.include?(k)) }
|
387
|
+
|
388
|
+
conditions
|
389
|
+
end
|
390
|
+
private :build_conditions
|
391
|
+
|
357
392
|
class Generator #:nodoc:
|
358
|
-
PARAMETERIZE =
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
return nil unless param = value.to_param
|
366
|
-
param.split('/').map { |v| Rack::Mount::Utils.escape_uri(v) }.join("/")
|
367
|
-
end
|
393
|
+
PARAMETERIZE = lambda do |name, value|
|
394
|
+
if name == :controller
|
395
|
+
value
|
396
|
+
elsif value.is_a?(Array)
|
397
|
+
value.map { |v| v.to_param }.join('/')
|
398
|
+
elsif param = value.to_param
|
399
|
+
param
|
368
400
|
end
|
369
|
-
|
401
|
+
end
|
370
402
|
|
371
403
|
attr_reader :options, :recall, :set, :named_route
|
372
404
|
|
@@ -456,14 +488,14 @@ module ActionDispatch
|
|
456
488
|
end
|
457
489
|
|
458
490
|
def generate
|
459
|
-
path, params = @set.
|
491
|
+
path, params = @set.formatter.generate(:path_info, named_route, options, recall, PARAMETERIZE)
|
460
492
|
|
461
493
|
raise_routing_error unless path
|
462
494
|
|
463
495
|
return [path, params.keys] if @extras
|
464
496
|
|
465
497
|
[path, params]
|
466
|
-
rescue
|
498
|
+
rescue Journey::Router::RoutingError
|
467
499
|
raise_routing_error
|
468
500
|
end
|
469
501
|
|
@@ -525,7 +557,7 @@ module ActionDispatch
|
|
525
557
|
path_addition, params = generate(path_options, path_segments || {})
|
526
558
|
path << path_addition
|
527
559
|
|
528
|
-
ActionDispatch::Http::URL.url_for(options.merge({
|
560
|
+
ActionDispatch::Http::URL.url_for(options.merge!({
|
529
561
|
:path => path,
|
530
562
|
:params => params,
|
531
563
|
:user => user,
|
@@ -535,12 +567,12 @@ module ActionDispatch
|
|
535
567
|
|
536
568
|
def call(env)
|
537
569
|
finalize!
|
538
|
-
@
|
570
|
+
@router.call(env)
|
539
571
|
end
|
540
572
|
|
541
573
|
def recognize_path(path, environment = {})
|
542
574
|
method = (environment[:method] || "GET").to_s.upcase
|
543
|
-
path =
|
575
|
+
path = Journey::Router::Utils.normalize_path(path) unless path =~ %r{://}
|
544
576
|
|
545
577
|
begin
|
546
578
|
env = Rack::MockRequest.env_for(path, {:method => method})
|
@@ -549,7 +581,7 @@ module ActionDispatch
|
|
549
581
|
end
|
550
582
|
|
551
583
|
req = @request_class.new(env)
|
552
|
-
@
|
584
|
+
@router.recognize(req) do |route, matches, params|
|
553
585
|
params.each do |key, value|
|
554
586
|
if value.is_a?(String)
|
555
587
|
value = value.dup.force_encoding(Encoding::BINARY) if value.encoding_aware?
|
@@ -16,10 +16,6 @@ module ActionDispatch
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
def respond_to?(method, include_private = false)
|
20
|
-
super || routes.url_helpers.respond_to?(method)
|
21
|
-
end
|
22
|
-
|
23
19
|
def method_missing(method, *args)
|
24
20
|
if routes.url_helpers.respond_to?(method)
|
25
21
|
self.class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
@@ -42,7 +42,7 @@ module ActionDispatch
|
|
42
42
|
# url_for(:controller => 'users',
|
43
43
|
# :action => 'new',
|
44
44
|
# :message => 'Welcome!',
|
45
|
-
# :host => 'www.example.com')
|
45
|
+
# :host => 'www.example.com')
|
46
46
|
# # => "http://www.example.com/users/new?message=Welcome%21"
|
47
47
|
#
|
48
48
|
# By default, all controllers and views have access to a special version of url_for,
|
@@ -108,7 +108,7 @@ module ActionDispatch
|
|
108
108
|
end
|
109
109
|
|
110
110
|
# Generate a url based on the options provided, default_url_options and the
|
111
|
-
# routes defined in routes.rb.
|
111
|
+
# routes defined in routes.rb. The following options are supported:
|
112
112
|
#
|
113
113
|
# * <tt>:only_path</tt> - If true, the relative url is returned. Defaults to +false+.
|
114
114
|
# * <tt>:protocol</tt> - The protocol to connect to. Defaults to 'http'.
|
@@ -145,7 +145,7 @@ module ActionDispatch
|
|
145
145
|
when String
|
146
146
|
options
|
147
147
|
when nil, Hash
|
148
|
-
_routes.url_for((options || {}).reverse_merge(url_options)
|
148
|
+
_routes.url_for((options || {}).symbolize_keys.reverse_merge!(url_options))
|
149
149
|
else
|
150
150
|
polymorphic_url(options)
|
151
151
|
end
|
@@ -55,16 +55,14 @@ module ActionDispatch
|
|
55
55
|
# assert_redirected_to @customer
|
56
56
|
#
|
57
57
|
def assert_redirected_to(options = {}, message=nil)
|
58
|
-
validate_request!
|
59
|
-
|
60
58
|
assert_response(:redirect, message)
|
61
59
|
return true if options == @response.location
|
62
60
|
|
63
|
-
|
64
|
-
|
61
|
+
redirect_is = normalize_argument_to_redirection(@response.location)
|
62
|
+
redirect_expected = normalize_argument_to_redirection(options)
|
65
63
|
|
66
|
-
if
|
67
|
-
flunk "Expected response to be a redirect to <#{
|
64
|
+
if redirect_is != redirect_expected
|
65
|
+
flunk "Expected response to be a redirect to <#{redirect_expected}> but was a redirect to <#{redirect_is}>"
|
68
66
|
end
|
69
67
|
end
|
70
68
|
|
@@ -85,7 +83,7 @@ module ActionDispatch
|
|
85
83
|
refer
|
86
84
|
else
|
87
85
|
@controller.url_for(fragment)
|
88
|
-
end.gsub(/[\
|
86
|
+
end.gsub(/[\r\n]/, '')
|
89
87
|
end
|
90
88
|
|
91
89
|
def validate_request!
|
@@ -1,24 +1,25 @@
|
|
1
1
|
require 'uri'
|
2
2
|
require 'active_support/core_ext/hash/diff'
|
3
3
|
require 'active_support/core_ext/hash/indifferent_access'
|
4
|
+
require 'action_controller/metal/exceptions'
|
4
5
|
|
5
6
|
module ActionDispatch
|
6
7
|
module Assertions
|
7
8
|
# Suite of assertions to test routes generated by \Rails and the handling of requests made to them.
|
8
9
|
module RoutingAssertions
|
9
10
|
# Asserts that the routing of the given +path+ was handled correctly and that the parsed options (given in the +expected_options+ hash)
|
10
|
-
# match +path+.
|
11
|
+
# match +path+. Basically, it asserts that \Rails recognizes the route given by +expected_options+.
|
11
12
|
#
|
12
|
-
# Pass a hash in the second argument (+path+) to specify the request method.
|
13
|
-
# requiring a specific HTTP method.
|
13
|
+
# Pass a hash in the second argument (+path+) to specify the request method. This is useful for routes
|
14
|
+
# requiring a specific HTTP method. The hash should contain a :path with the incoming request path
|
14
15
|
# and a :method containing the required HTTP verb.
|
15
16
|
#
|
16
17
|
# # assert that POSTing to /items will call the create action on ItemsController
|
17
18
|
# assert_recognizes({:controller => 'items', :action => 'create'}, {:path => 'items', :method => :post})
|
18
19
|
#
|
19
|
-
# You can also pass in +extras+ with a hash containing URL parameters that would normally be in the query string.
|
20
|
-
# to assert that values in the query string string will end up in the params hash correctly.
|
21
|
-
# extras argument, appending the query string on the path directly will not work.
|
20
|
+
# You can also pass in +extras+ with a hash containing URL parameters that would normally be in the query string. This can be used
|
21
|
+
# to assert that values in the query string string will end up in the params hash correctly. To test query strings you must use the
|
22
|
+
# extras argument, appending the query string on the path directly will not work. For example:
|
22
23
|
#
|
23
24
|
# # assert that a path of '/items/list/1?view=print' returns the correct options
|
24
25
|
# assert_recognizes({:controller => 'items', :action => 'list', :id => '1', :view => 'print'}, 'items/list/1', { :view => "print" })
|
@@ -49,7 +50,7 @@ module ActionDispatch
|
|
49
50
|
assert_equal(expected_options, request.path_parameters, msg)
|
50
51
|
end
|
51
52
|
|
52
|
-
# Asserts that the provided options can be used to generate the provided path.
|
53
|
+
# Asserts that the provided options can be used to generate the provided path. This is the inverse of +assert_recognizes+.
|
53
54
|
# The +extras+ parameter is used to tell the request the names and values of additional request parameters that would be in
|
54
55
|
# a query string. The +message+ parameter allows you to specify a custom error message for assertion failures.
|
55
56
|
#
|
@@ -92,10 +93,10 @@ module ActionDispatch
|
|
92
93
|
end
|
93
94
|
|
94
95
|
# Asserts that path and options match both ways; in other words, it verifies that <tt>path</tt> generates
|
95
|
-
# <tt>options</tt> and then that <tt>options</tt> generates <tt>path</tt>.
|
96
|
+
# <tt>options</tt> and then that <tt>options</tt> generates <tt>path</tt>. This essentially combines +assert_recognizes+
|
96
97
|
# and +assert_generates+ into one step.
|
97
98
|
#
|
98
|
-
# The +extras+ hash allows you to specify options that would normally be provided as a query string to the action.
|
99
|
+
# The +extras+ hash allows you to specify options that would normally be provided as a query string to the action. The
|
99
100
|
# +message+ parameter allows you to specify a custom error message to display upon failure.
|
100
101
|
#
|
101
102
|
# ==== Examples
|