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.

Files changed (128) hide show
  1. data/CHANGELOG.md +5503 -108
  2. data/README.rdoc +3 -3
  3. data/lib/abstract_controller/asset_paths.rb +1 -1
  4. data/lib/abstract_controller/base.rb +1 -1
  5. data/lib/abstract_controller/callbacks.rb +102 -18
  6. data/lib/abstract_controller/helpers.rb +1 -1
  7. data/lib/abstract_controller/layouts.rb +116 -50
  8. data/lib/abstract_controller/logger.rb +1 -1
  9. data/lib/abstract_controller/railties/routes_helpers.rb +2 -2
  10. data/lib/abstract_controller/rendering.rb +1 -6
  11. data/lib/abstract_controller/view_paths.rb +6 -5
  12. data/lib/action_controller.rb +0 -15
  13. data/lib/action_controller/caching.rb +0 -1
  14. data/lib/action_controller/caching/actions.rb +5 -6
  15. data/lib/action_controller/caching/fragments.rb +18 -18
  16. data/lib/action_controller/caching/pages.rb +7 -6
  17. data/lib/action_controller/caching/sweeping.rb +1 -1
  18. data/lib/action_controller/log_subscriber.rb +8 -4
  19. data/lib/action_controller/metal.rb +7 -1
  20. data/lib/action_controller/metal/conditional_get.rb +49 -4
  21. data/lib/action_controller/metal/data_streaming.rb +17 -5
  22. data/lib/action_controller/metal/force_ssl.rb +8 -5
  23. data/lib/action_controller/metal/helpers.rb +7 -4
  24. data/lib/action_controller/metal/http_authentication.rb +9 -12
  25. data/lib/action_controller/metal/instrumentation.rb +9 -4
  26. data/lib/action_controller/metal/mime_responds.rb +4 -4
  27. data/lib/action_controller/metal/params_wrapper.rb +12 -8
  28. data/lib/action_controller/metal/redirecting.rb +7 -6
  29. data/lib/action_controller/metal/renderers.rb +9 -11
  30. data/lib/action_controller/metal/request_forgery_protection.rb +2 -1
  31. data/lib/action_controller/metal/rescue.rb +13 -0
  32. data/lib/action_controller/metal/responder.rb +11 -23
  33. data/lib/action_controller/metal/streaming.rb +0 -25
  34. data/lib/action_controller/railtie.rb +1 -0
  35. data/lib/action_controller/railties/paths.rb +4 -3
  36. data/lib/action_controller/record_identifier.rb +4 -4
  37. data/lib/action_controller/test_case.rb +60 -56
  38. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +6 -6
  39. data/lib/action_dispatch.rb +5 -1
  40. data/lib/action_dispatch/http/cache.rb +27 -15
  41. data/lib/action_dispatch/http/filter_parameters.rb +3 -1
  42. data/lib/action_dispatch/http/headers.rb +3 -5
  43. data/lib/action_dispatch/http/mime_negotiation.rb +2 -1
  44. data/lib/action_dispatch/http/mime_type.rb +7 -3
  45. data/lib/action_dispatch/http/mime_types.rb +12 -0
  46. data/lib/action_dispatch/http/parameter_filter.rb +3 -1
  47. data/lib/action_dispatch/http/parameters.rb +0 -4
  48. data/lib/action_dispatch/http/request.rb +18 -68
  49. data/lib/action_dispatch/http/response.rb +11 -32
  50. data/lib/action_dispatch/http/upload.rb +3 -14
  51. data/lib/action_dispatch/http/url.rb +1 -1
  52. data/lib/action_dispatch/middleware/callbacks.rb +1 -2
  53. data/lib/action_dispatch/middleware/cookies.rb +20 -16
  54. data/lib/action_dispatch/middleware/debug_exceptions.rb +82 -0
  55. data/lib/action_dispatch/middleware/exception_wrapper.rb +78 -0
  56. data/lib/action_dispatch/middleware/flash.rb +6 -9
  57. data/lib/action_dispatch/middleware/params_parser.rb +6 -11
  58. data/lib/action_dispatch/middleware/public_exceptions.rb +30 -0
  59. data/lib/action_dispatch/middleware/reloader.rb +38 -14
  60. data/lib/action_dispatch/middleware/remote_ip.rb +66 -36
  61. data/lib/action_dispatch/middleware/request_id.rb +39 -0
  62. data/lib/action_dispatch/middleware/session/abstract_store.rb +4 -16
  63. data/lib/action_dispatch/middleware/session/cache_store.rb +50 -0
  64. data/lib/action_dispatch/middleware/session/cookie_store.rb +1 -1
  65. data/lib/action_dispatch/middleware/show_exceptions.rb +58 -142
  66. data/lib/action_dispatch/middleware/static.rb +2 -10
  67. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +1 -0
  68. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +13 -8
  69. data/lib/action_dispatch/railtie.rb +15 -1
  70. data/lib/action_dispatch/routing.rb +1 -2
  71. data/lib/action_dispatch/routing/mapper.rb +108 -107
  72. data/lib/action_dispatch/routing/redirection.rb +63 -69
  73. data/lib/action_dispatch/routing/route_set.rb +75 -43
  74. data/lib/action_dispatch/routing/routes_proxy.rb +0 -4
  75. data/lib/action_dispatch/routing/url_for.rb +3 -3
  76. data/lib/action_dispatch/testing/assertions/response.rb +5 -7
  77. data/lib/action_dispatch/testing/assertions/routing.rb +10 -9
  78. data/lib/action_dispatch/testing/integration.rb +8 -25
  79. data/lib/action_dispatch/testing/test_process.rb +3 -2
  80. data/lib/action_dispatch/testing/test_request.rb +4 -23
  81. data/lib/action_pack/version.rb +3 -3
  82. data/lib/action_view.rb +1 -5
  83. data/lib/action_view/asset_paths.rb +7 -8
  84. data/lib/action_view/base.rb +7 -5
  85. data/lib/action_view/helpers/asset_paths.rb +1 -1
  86. data/lib/action_view/helpers/asset_tag_helper.rb +4 -8
  87. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +3 -0
  88. data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
  89. data/lib/action_view/helpers/capture_helper.rb +3 -3
  90. data/lib/action_view/helpers/controller_helper.rb +1 -1
  91. data/lib/action_view/helpers/date_helper.rb +26 -18
  92. data/lib/action_view/helpers/debug_helper.rb +1 -1
  93. data/lib/action_view/helpers/form_helper.rb +71 -13
  94. data/lib/action_view/helpers/form_options_helper.rb +65 -34
  95. data/lib/action_view/helpers/form_tag_helper.rb +24 -18
  96. data/lib/action_view/helpers/javascript_helper.rb +12 -3
  97. data/lib/action_view/helpers/number_helper.rb +3 -2
  98. data/lib/action_view/helpers/record_tag_helper.rb +51 -5
  99. data/lib/action_view/helpers/rendering_helper.rb +2 -2
  100. data/lib/action_view/helpers/sanitize_helper.rb +6 -7
  101. data/lib/action_view/helpers/tag_helper.rb +1 -1
  102. data/lib/action_view/helpers/text_helper.rb +5 -4
  103. data/lib/action_view/helpers/url_helper.rb +19 -11
  104. data/lib/action_view/locale/en.yml +6 -0
  105. data/lib/action_view/log_subscriber.rb +1 -1
  106. data/lib/action_view/lookup_context.rb +123 -125
  107. data/lib/action_view/path_set.rb +60 -13
  108. data/lib/action_view/renderer/abstract_renderer.rb +16 -11
  109. data/lib/action_view/renderer/partial_renderer.rb +59 -40
  110. data/lib/action_view/renderer/template_renderer.rb +29 -17
  111. data/lib/action_view/template.rb +0 -1
  112. data/lib/action_view/template/error.rb +6 -5
  113. data/lib/action_view/template/handlers.rb +0 -6
  114. data/lib/action_view/template/handlers/builder.rb +10 -1
  115. data/lib/action_view/template/handlers/erb.rb +2 -2
  116. data/lib/action_view/template/resolver.rb +20 -31
  117. data/lib/action_view/test_case.rb +7 -10
  118. data/lib/sprockets/assets.rake +1 -1
  119. data/lib/sprockets/bootstrap.rb +3 -31
  120. data/lib/sprockets/compressors.rb +69 -7
  121. data/lib/sprockets/helpers/rails_helper.rb +6 -11
  122. data/lib/sprockets/railtie.rb +1 -0
  123. data/lib/sprockets/static_compiler.rb +0 -3
  124. metadata +57 -86
  125. checksums.yaml +0 -7
  126. data/lib/action_dispatch/middleware/closed_error.rb +0 -7
  127. data/lib/action_dispatch/routing/route.rb +0 -67
  128. 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
- path = args.shift
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
- def redirection_proc(status, path_proc)
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
- body = %(<html><body>You are being <a href="#{ERB::Util.h(uri.to_s)}">redirected</a>.</body></html>)
95
+ block = lambda { |params, request|
96
+ (params.empty? || !path.match(/%\{\w*\}/)) ? path : (path % params)
97
+ } if String === path
99
98
 
100
- headers = {
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
- [ status, headers, [body] ]
107
- end
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
- def escape(params)
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 'rack/mount'
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
- # an user error. However, if the controller was retrieved through a dynamic
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.size > 0
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 :set, :routes, :named_routes, :default_scope
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
- self.valid_conditions = request_class.public_instance_methods.map { |m| m.to_sym }
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
- clear!
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
- @set = ::Rack::Mount::RouteSet.new(
280
- :parameters_key => PARAMETERS_KEY,
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
- route = Route.new(self, app, conditions, requirements, defaults, name, anchor)
351
- @set.add_route(route.app, route.conditions, route.defaults, route.name)
352
- named_routes[name] = route if name
353
- routes << route
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
- :parameterize => lambda do |name, value|
360
- if name == :controller
361
- value
362
- elsif value.is_a?(Array)
363
- value.map { |v| Rack::Mount::Utils.escape_uri(v.to_param) }.join('/')
364
- else
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.set.generate(:path_info, named_route, options, recall, PARAMETERIZE)
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 Rack::Mount::RoutingError
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
- @set.call(env)
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 = Rack::Mount::Utils.normalize_path(path) unless path =~ %r{://}
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
- @set.recognize(req) do |route, matches, params|
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') # Changed this.
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. The following options are supported:
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).symbolize_keys)
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
- redirected_to_after_normalisation = normalize_argument_to_redirection(@response.location)
64
- options_after_normalisation = normalize_argument_to_redirection(options)
61
+ redirect_is = normalize_argument_to_redirection(@response.location)
62
+ redirect_expected = normalize_argument_to_redirection(options)
65
63
 
66
- if redirected_to_after_normalisation != options_after_normalisation
67
- flunk "Expected response to be a redirect to <#{options_after_normalisation}> but was a redirect to <#{redirected_to_after_normalisation}>"
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(/[\0\r\n]/, '')
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+. Basically, it asserts that \Rails recognizes the route given by +expected_options+.
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. This is useful for routes
13
- # requiring a specific HTTP method. The hash should contain a :path with the incoming request path
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. This can be used
20
- # 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
21
- # extras argument, appending the query string on the path directly will not work. For example:
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. This is the inverse of +assert_recognizes+.
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>. This essentially combines +assert_recognizes+
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. The
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