actionpack 5.0.7.2 → 5.1.0.beta1

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. checksums.yaml +5 -5
  2. data/CHANGELOG.md +189 -1002
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/abstract_controller.rb +3 -3
  6. data/lib/abstract_controller/base.rb +10 -12
  7. data/lib/abstract_controller/caching.rb +6 -3
  8. data/lib/abstract_controller/caching/fragments.rb +1 -1
  9. data/lib/abstract_controller/callbacks.rb +2 -43
  10. data/lib/abstract_controller/collector.rb +2 -2
  11. data/lib/abstract_controller/helpers.rb +19 -19
  12. data/lib/abstract_controller/rendering.rb +9 -11
  13. data/lib/abstract_controller/translation.rb +3 -3
  14. data/lib/action_controller.rb +15 -13
  15. data/lib/action_controller/api.rb +3 -3
  16. data/lib/action_controller/base.rb +7 -12
  17. data/lib/action_controller/caching.rb +1 -1
  18. data/lib/action_controller/log_subscriber.rb +2 -2
  19. data/lib/action_controller/metal.rb +34 -43
  20. data/lib/action_controller/metal/conditional_get.rb +10 -9
  21. data/lib/action_controller/metal/data_streaming.rb +8 -9
  22. data/lib/action_controller/metal/etag_with_flash.rb +16 -0
  23. data/lib/action_controller/metal/etag_with_template_digest.rb +15 -15
  24. data/lib/action_controller/metal/exceptions.rb +4 -14
  25. data/lib/action_controller/metal/flash.rb +1 -1
  26. data/lib/action_controller/metal/force_ssl.rb +6 -6
  27. data/lib/action_controller/metal/head.rb +13 -19
  28. data/lib/action_controller/metal/helpers.rb +6 -6
  29. data/lib/action_controller/metal/http_authentication.rb +22 -23
  30. data/lib/action_controller/metal/implicit_render.rb +2 -5
  31. data/lib/action_controller/metal/instrumentation.rb +14 -14
  32. data/lib/action_controller/metal/live.rb +15 -16
  33. data/lib/action_controller/metal/mime_responds.rb +3 -3
  34. data/lib/action_controller/metal/parameter_encoding.rb +49 -0
  35. data/lib/action_controller/metal/params_wrapper.rb +32 -32
  36. data/lib/action_controller/metal/redirecting.rb +8 -24
  37. data/lib/action_controller/metal/renderers.rb +2 -3
  38. data/lib/action_controller/metal/rendering.rb +50 -60
  39. data/lib/action_controller/metal/request_forgery_protection.rb +51 -49
  40. data/lib/action_controller/metal/rescue.rb +1 -1
  41. data/lib/action_controller/metal/streaming.rb +4 -4
  42. data/lib/action_controller/metal/strong_parameters.rb +117 -250
  43. data/lib/action_controller/metal/testing.rb +1 -1
  44. data/lib/action_controller/metal/url_for.rb +4 -4
  45. data/lib/action_controller/railtie.rb +9 -13
  46. data/lib/action_controller/renderer.rb +17 -16
  47. data/lib/action_controller/test_case.rb +75 -148
  48. data/lib/action_dispatch.rb +20 -19
  49. data/lib/action_dispatch/http/cache.rb +9 -10
  50. data/lib/action_dispatch/http/filter_parameters.rb +8 -8
  51. data/lib/action_dispatch/http/filter_redirect.rb +2 -4
  52. data/lib/action_dispatch/http/headers.rb +10 -10
  53. data/lib/action_dispatch/http/mime_negotiation.rb +17 -22
  54. data/lib/action_dispatch/http/mime_type.rb +27 -52
  55. data/lib/action_dispatch/http/parameter_filter.rb +8 -6
  56. data/lib/action_dispatch/http/parameters.rb +40 -17
  57. data/lib/action_dispatch/http/request.rb +38 -34
  58. data/lib/action_dispatch/http/response.rb +16 -16
  59. data/lib/action_dispatch/http/upload.rb +6 -10
  60. data/lib/action_dispatch/http/url.rb +48 -74
  61. data/lib/action_dispatch/journey.rb +5 -5
  62. data/lib/action_dispatch/journey/formatter.rb +8 -4
  63. data/lib/action_dispatch/journey/gtg/builder.rb +5 -5
  64. data/lib/action_dispatch/journey/gtg/simulator.rb +1 -1
  65. data/lib/action_dispatch/journey/gtg/transition_table.rb +15 -15
  66. data/lib/action_dispatch/journey/nfa/builder.rb +3 -3
  67. data/lib/action_dispatch/journey/nfa/dot.rb +2 -2
  68. data/lib/action_dispatch/journey/nfa/simulator.rb +1 -1
  69. data/lib/action_dispatch/journey/nfa/transition_table.rb +2 -2
  70. data/lib/action_dispatch/journey/nodes/node.rb +5 -5
  71. data/lib/action_dispatch/journey/parser.rb +23 -24
  72. data/lib/action_dispatch/journey/parser.y +3 -2
  73. data/lib/action_dispatch/journey/parser_extras.rb +2 -2
  74. data/lib/action_dispatch/journey/path/pattern.rb +10 -3
  75. data/lib/action_dispatch/journey/route.rb +19 -12
  76. data/lib/action_dispatch/journey/router.rb +19 -12
  77. data/lib/action_dispatch/journey/router/utils.rb +9 -9
  78. data/lib/action_dispatch/journey/scanner.rb +17 -15
  79. data/lib/action_dispatch/journey/visitors.rb +23 -23
  80. data/lib/action_dispatch/middleware/callbacks.rb +0 -12
  81. data/lib/action_dispatch/middleware/cookies.rb +39 -39
  82. data/lib/action_dispatch/middleware/debug_exceptions.rb +126 -112
  83. data/lib/action_dispatch/middleware/debug_locks.rb +8 -8
  84. data/lib/action_dispatch/middleware/exception_wrapper.rb +55 -55
  85. data/lib/action_dispatch/middleware/executor.rb +1 -1
  86. data/lib/action_dispatch/middleware/flash.rb +17 -16
  87. data/lib/action_dispatch/middleware/public_exceptions.rb +20 -20
  88. data/lib/action_dispatch/middleware/reloader.rb +3 -47
  89. data/lib/action_dispatch/middleware/remote_ip.rb +6 -8
  90. data/lib/action_dispatch/middleware/request_id.rb +6 -5
  91. data/lib/action_dispatch/middleware/session/abstract_store.rb +14 -26
  92. data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
  93. data/lib/action_dispatch/middleware/session/cookie_store.rb +35 -35
  94. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +2 -2
  95. data/lib/action_dispatch/middleware/show_exceptions.rb +19 -19
  96. data/lib/action_dispatch/middleware/ssl.rb +9 -27
  97. data/lib/action_dispatch/middleware/stack.rb +7 -26
  98. data/lib/action_dispatch/middleware/static.rb +13 -24
  99. data/lib/action_dispatch/railtie.rb +9 -11
  100. data/lib/action_dispatch/request/session.rb +22 -22
  101. data/lib/action_dispatch/request/utils.rb +11 -2
  102. data/lib/action_dispatch/routing.rb +8 -6
  103. data/lib/action_dispatch/routing/inspector.rb +37 -37
  104. data/lib/action_dispatch/routing/mapper.rb +296 -203
  105. data/lib/action_dispatch/routing/polymorphic_routes.rb +160 -134
  106. data/lib/action_dispatch/routing/redirection.rb +27 -22
  107. data/lib/action_dispatch/routing/route_set.rb +206 -92
  108. data/lib/action_dispatch/routing/routes_proxy.rb +2 -2
  109. data/lib/action_dispatch/routing/url_for.rb +14 -12
  110. data/lib/action_dispatch/system_test_case.rb +119 -0
  111. data/lib/action_dispatch/system_testing/browser.rb +28 -0
  112. data/lib/action_dispatch/system_testing/driver.rb +18 -0
  113. data/lib/action_dispatch/system_testing/server.rb +32 -0
  114. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +61 -0
  115. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +20 -0
  116. data/lib/action_dispatch/testing/assertion_response.rb +6 -6
  117. data/lib/action_dispatch/testing/assertions.rb +4 -4
  118. data/lib/action_dispatch/testing/assertions/response.rb +8 -3
  119. data/lib/action_dispatch/testing/assertions/routing.rb +11 -11
  120. data/lib/action_dispatch/testing/integration.rb +47 -138
  121. data/lib/action_dispatch/testing/test_process.rb +2 -2
  122. data/lib/action_dispatch/testing/test_request.rb +16 -16
  123. data/lib/action_dispatch/testing/test_response.rb +1 -1
  124. data/lib/action_pack.rb +2 -2
  125. data/lib/action_pack/gem_version.rb +3 -3
  126. data/lib/action_pack/version.rb +1 -1
  127. metadata +20 -12
  128. data/lib/action_dispatch/middleware/params_parser.rb +0 -46
@@ -1,12 +1,11 @@
1
- require 'action_dispatch/journey'
2
- require 'active_support/concern'
3
- require 'active_support/core_ext/object/to_query'
4
- require 'active_support/core_ext/hash/slice'
5
- require 'active_support/core_ext/module/remove_method'
6
- require 'active_support/core_ext/array/extract_options'
7
- require 'action_controller/metal/exceptions'
8
- require 'action_dispatch/http/request'
9
- require 'action_dispatch/routing/endpoint'
1
+ require "action_dispatch/journey"
2
+ require "active_support/core_ext/object/to_query"
3
+ require "active_support/core_ext/hash/slice"
4
+ require "active_support/core_ext/module/remove_method"
5
+ require "active_support/core_ext/array/extract_options"
6
+ require "action_controller/metal/exceptions"
7
+ require "action_dispatch/http/request"
8
+ require "action_dispatch/routing/endpoint"
10
9
 
11
10
  module ActionDispatch
12
11
  module Routing
@@ -34,7 +33,7 @@ module ActionDispatch
34
33
  if @raise_on_name_error
35
34
  raise
36
35
  else
37
- return [404, {'X-Cascade' => 'pass'}, []]
36
+ return [404, { "X-Cascade" => "pass" }, []]
38
37
  end
39
38
  end
40
39
 
@@ -59,7 +58,7 @@ module ActionDispatch
59
58
 
60
59
  private
61
60
 
62
- def controller(_); @controller_class; end
61
+ def controller(_); @controller_class; end
63
62
  end
64
63
 
65
64
  # A NamedRouteCollection instance is a collection of named routes, and also
@@ -71,9 +70,10 @@ module ActionDispatch
71
70
  private :routes
72
71
 
73
72
  def initialize
74
- @routes = {}
73
+ @routes = {}
75
74
  @path_helpers = Set.new
76
75
  @url_helpers = Set.new
76
+ @custom_helpers = Set.new
77
77
  @url_helpers_module = Module.new
78
78
  @path_helpers_module = Module.new
79
79
  end
@@ -89,16 +89,30 @@ module ActionDispatch
89
89
 
90
90
  def clear!
91
91
  @path_helpers.each do |helper|
92
- @path_helpers_module.send :undef_method, helper
92
+ @path_helpers_module.send :remove_method, helper
93
93
  end
94
94
 
95
95
  @url_helpers.each do |helper|
96
- @url_helpers_module.send :undef_method, helper
96
+ @url_helpers_module.send :remove_method, helper
97
+ end
98
+
99
+ @custom_helpers.each do |helper|
100
+ path_name = :"#{helper}_path"
101
+ url_name = :"#{helper}_url"
102
+
103
+ if @path_helpers_module.method_defined?(path_name)
104
+ @path_helpers_module.send :remove_method, path_name
105
+ end
106
+
107
+ if @url_helpers_module.method_defined?(url_name)
108
+ @url_helpers_module.send :remove_method, url_name
109
+ end
97
110
  end
98
111
 
99
112
  @routes.clear
100
113
  @path_helpers.clear
101
114
  @url_helpers.clear
115
+ @custom_helpers.clear
102
116
  end
103
117
 
104
118
  def add(name, route)
@@ -144,6 +158,23 @@ module ActionDispatch
144
158
  routes.length
145
159
  end
146
160
 
161
+ def add_url_helper(name, defaults, &block)
162
+ @custom_helpers << name
163
+ helper = CustomUrlHelper.new(name, defaults, &block)
164
+
165
+ @path_helpers_module.module_eval do
166
+ define_method(:"#{name}_path") do |*args|
167
+ helper.call(self, args, only_path: true)
168
+ end
169
+ end
170
+
171
+ @url_helpers_module.module_eval do
172
+ define_method(:"#{name}_url") do |*args|
173
+ helper.call(self, args)
174
+ end
175
+ end
176
+ end
177
+
147
178
  class UrlHelper
148
179
  def self.create(route, options, route_name, url_strategy)
149
180
  if optimize_helper?(route)
@@ -180,40 +211,40 @@ module ActionDispatch
180
211
 
181
212
  private
182
213
 
183
- def optimized_helper(args)
184
- params = parameterize_args(args) do
185
- raise_generation_error(args)
186
- end
214
+ def optimized_helper(args)
215
+ params = parameterize_args(args) do
216
+ raise_generation_error(args)
217
+ end
187
218
 
188
- @route.format params
189
- end
219
+ @route.format params
220
+ end
190
221
 
191
- def optimize_routes_generation?(t)
192
- t.send(:optimize_routes_generation?)
193
- end
222
+ def optimize_routes_generation?(t)
223
+ t.send(:optimize_routes_generation?)
224
+ end
194
225
 
195
- def parameterize_args(args)
196
- params = {}
197
- @arg_size.times { |i|
198
- key = @required_parts[i]
199
- value = args[i].to_param
200
- yield key if value.nil? || value.empty?
201
- params[key] = value
202
- }
203
- params
204
- end
226
+ def parameterize_args(args)
227
+ params = {}
228
+ @arg_size.times { |i|
229
+ key = @required_parts[i]
230
+ value = args[i].to_param
231
+ yield key if value.nil? || value.empty?
232
+ params[key] = value
233
+ }
234
+ params
235
+ end
205
236
 
206
- def raise_generation_error(args)
207
- missing_keys = []
208
- params = parameterize_args(args) { |missing_key|
209
- missing_keys << missing_key
210
- }
211
- constraints = Hash[@route.requirements.merge(params).sort_by{|k,v| k.to_s}]
212
- message = "No route matches #{constraints.inspect}"
213
- message << " missing required keys: #{missing_keys.sort.inspect}"
237
+ def raise_generation_error(args)
238
+ missing_keys = []
239
+ params = parameterize_args(args) { |missing_key|
240
+ missing_keys << missing_key
241
+ }
242
+ constraints = Hash[@route.requirements.merge(params).sort_by { |k, v| k.to_s }]
243
+ message = "No route matches #{constraints.inspect}"
244
+ message << ", missing required keys: #{missing_keys.sort.inspect}"
214
245
 
215
- raise ActionController::UrlGenerationError, message
216
- end
246
+ raise ActionController::UrlGenerationError, message
247
+ end
217
248
  end
218
249
 
219
250
  def initialize(route, options, route_name, url_strategy)
@@ -248,8 +279,6 @@ module ActionDispatch
248
279
  if args.size < path_params_size
249
280
  path_params -= controller_options.keys
250
281
  path_params -= result.keys
251
- else
252
- path_params = path_params.dup
253
282
  end
254
283
  inner_options.each_key do |key|
255
284
  path_params.delete(key)
@@ -266,38 +295,39 @@ module ActionDispatch
266
295
  end
267
296
 
268
297
  private
269
- # Create a url helper allowing ordered parameters to be associated
270
- # with corresponding dynamic segments, so you can do:
271
- #
272
- # foo_url(bar, baz, bang)
273
- #
274
- # Instead of:
275
- #
276
- # foo_url(bar: bar, baz: baz, bang: bang)
277
- #
278
- # Also allow options hash, so you can do:
279
- #
280
- # foo_url(bar, baz, bang, sort_by: 'baz')
281
- #
282
- def define_url_helper(mod, route, name, opts, route_key, url_strategy)
283
- helper = UrlHelper.create(route, opts, route_key, url_strategy)
284
- mod.module_eval do
285
- define_method(name) do |*args|
286
- last = args.last
287
- options = case last
288
- when Hash
289
- args.pop
290
- when ActionController::Parameters
291
- if last.permitted?
292
- args.pop.to_h
293
- else
294
- raise ArgumentError, ActionDispatch::Routing::INSECURE_URL_PARAMETERS_MESSAGE
295
- end
296
- end
297
- helper.call self, args, options
298
+ # Create a url helper allowing ordered parameters to be associated
299
+ # with corresponding dynamic segments, so you can do:
300
+ #
301
+ # foo_url(bar, baz, bang)
302
+ #
303
+ # Instead of:
304
+ #
305
+ # foo_url(bar: bar, baz: baz, bang: bang)
306
+ #
307
+ # Also allow options hash, so you can do:
308
+ #
309
+ # foo_url(bar, baz, bang, sort_by: 'baz')
310
+ #
311
+ def define_url_helper(mod, route, name, opts, route_key, url_strategy)
312
+ helper = UrlHelper.create(route, opts, route_key, url_strategy)
313
+ mod.module_eval do
314
+ define_method(name) do |*args|
315
+ last = args.last
316
+ options = \
317
+ case last
318
+ when Hash
319
+ args.pop
320
+ when ActionController::Parameters
321
+ if last.permitted?
322
+ args.pop.to_h
323
+ else
324
+ raise ArgumentError, ActionDispatch::Routing::INSECURE_URL_PARAMETERS_MESSAGE
325
+ end
326
+ end
327
+ helper.call self, args, options
328
+ end
298
329
  end
299
330
  end
300
- end
301
331
  end
302
332
 
303
333
  # strategy for building urls to send to the client
@@ -307,12 +337,12 @@ module ActionDispatch
307
337
  attr_accessor :formatter, :set, :named_routes, :default_scope, :router
308
338
  attr_accessor :disable_clear_and_finalize, :resources_path_names
309
339
  attr_accessor :default_url_options
310
- attr_reader :env_key
340
+ attr_reader :env_key, :polymorphic_mappings
311
341
 
312
342
  alias :routes :set
313
343
 
314
344
  def self.default_resources_path_names
315
- { :new => 'new', :edit => 'edit' }
345
+ { new: "new", edit: "edit" }
316
346
  end
317
347
 
318
348
  def self.new_with_config(config)
@@ -349,6 +379,13 @@ module ActionDispatch
349
379
  @set = Journey::Routes.new
350
380
  @router = Journey::Router.new @set
351
381
  @formatter = Journey::Formatter.new self
382
+ @polymorphic_mappings = {}
383
+ end
384
+
385
+ def eager_load!
386
+ router.eager_load!
387
+ routes.each(&:eager_load!)
388
+ nil
352
389
  end
353
390
 
354
391
  def relative_url_root
@@ -404,6 +441,7 @@ module ActionDispatch
404
441
  named_routes.clear
405
442
  set.clear
406
443
  formatter.clear
444
+ @polymorphic_mappings.clear
407
445
  @prepend.each { |blk| eval_block(blk) }
408
446
  end
409
447
 
@@ -448,17 +486,42 @@ module ActionDispatch
448
486
 
449
487
  # Define url_for in the singleton level so one can do:
450
488
  # Rails.application.routes.url_helpers.url_for(args)
451
- @_routes = routes
489
+ proxy_class = Class.new do
490
+ include UrlFor
491
+ include routes.named_routes.path_helpers_module
492
+ include routes.named_routes.url_helpers_module
493
+
494
+ attr_reader :_routes
495
+
496
+ def initialize(routes)
497
+ @_routes = routes
498
+ end
499
+
500
+ def optimize_routes_generation?
501
+ @_routes.optimize_routes_generation?
502
+ end
503
+ end
504
+
505
+ @_proxy = proxy_class.new(routes)
506
+
452
507
  class << self
453
508
  def url_for(options)
454
- @_routes.url_for(options)
509
+ @_proxy.url_for(options)
455
510
  end
456
511
 
457
512
  def optimize_routes_generation?
458
- @_routes.optimize_routes_generation?
513
+ @_proxy.optimize_routes_generation?
459
514
  end
460
515
 
461
- attr_reader :_routes
516
+ def polymorphic_url(record_or_hash_or_array, options = {})
517
+ @_proxy.polymorphic_url(record_or_hash_or_array, options)
518
+ end
519
+
520
+ def polymorphic_path(record_or_hash_or_array, options = {})
521
+ @_proxy.polymorphic_path(record_or_hash_or_array, options)
522
+ end
523
+
524
+ def _routes; @_proxy._routes; end
462
525
  def url_options; {}; end
463
526
  end
464
527
 
@@ -533,6 +596,56 @@ module ActionDispatch
533
596
  route
534
597
  end
535
598
 
599
+ def add_polymorphic_mapping(klass, options, &block)
600
+ @polymorphic_mappings[klass] = CustomUrlHelper.new(klass, options, &block)
601
+ end
602
+
603
+ def add_url_helper(name, options, &block)
604
+ named_routes.add_url_helper(name, options, &block)
605
+ end
606
+
607
+ class CustomUrlHelper
608
+ attr_reader :name, :defaults, :block
609
+
610
+ def initialize(name, defaults, &block)
611
+ @name = name
612
+ @defaults = defaults
613
+ @block = block
614
+ end
615
+
616
+ def call(t, args, outer_options = {})
617
+ options = args.extract_options!
618
+ url_options = eval_block(t, args, options)
619
+
620
+ case url_options
621
+ when String
622
+ t.url_for(url_options)
623
+ when Hash
624
+ t.url_for(url_options.merge(outer_options))
625
+ when ActionController::Parameters
626
+ if url_options.permitted?
627
+ t.url_for(url_options.to_h.merge(outer_options))
628
+ else
629
+ raise ArgumentError, "Generating a URL from non sanitized request parameters is insecure!"
630
+ end
631
+ when Array
632
+ opts = url_options.extract_options!
633
+ t.url_for(url_options.push(opts.merge(outer_options)))
634
+ else
635
+ t.url_for([url_options, outer_options])
636
+ end
637
+ end
638
+
639
+ private
640
+ def eval_block(t, args, options)
641
+ t.instance_exec(*args, merge_defaults(options), &block)
642
+ end
643
+
644
+ def merge_defaults(options)
645
+ defaults ? defaults.merge(options) : options
646
+ end
647
+ end
648
+
536
649
  class Generator
537
650
  PARAMETERIZE = lambda do |name, value|
538
651
  if name == :controller
@@ -583,12 +696,12 @@ module ActionDispatch
583
696
  # be "index", not the recalled action of "show".
584
697
 
585
698
  if options[:controller]
586
- options[:action] ||= 'index'
699
+ options[:action] ||= "index"
587
700
  options[:controller] = options[:controller].to_s
588
701
  end
589
702
 
590
703
  if options.key?(:action)
591
- options[:action] = (options[:action] || 'index').to_s
704
+ options[:action] = (options[:action] || "index").to_s
592
705
  end
593
706
  end
594
707
 
@@ -598,8 +711,8 @@ module ActionDispatch
598
711
  # :controller, :action or :id is not found, don't pull any
599
712
  # more keys from the recall.
600
713
  def normalize_controller_action_id!
601
- use_recall_for(:controller) or return
602
- use_recall_for(:action) or return
714
+ use_recall_for(:controller) || return
715
+ use_recall_for(:action) || return
603
716
  use_recall_for(:id)
604
717
  end
605
718
 
@@ -607,7 +720,7 @@ module ActionDispatch
607
720
  # is specified, the controller becomes "foo/baz/bat"
608
721
  def use_relative_controller!
609
722
  if !named_route && different_controller? && !controller.start_with?("/")
610
- old_parts = current_controller.split('/')
723
+ old_parts = current_controller.split("/")
611
724
  size = controller.count("/") + 1
612
725
  parts = old_parts[0...-size] << controller
613
726
  @options[:controller] = parts.join("/")
@@ -648,11 +761,11 @@ module ActionDispatch
648
761
 
649
762
  # Generate the path indicated by the arguments, and return an array of
650
763
  # the keys that were not used to generate it.
651
- def extra_keys(options, recall={})
764
+ def extra_keys(options, recall = {})
652
765
  generate_extras(options, recall).last
653
766
  end
654
767
 
655
- def generate_extras(options, recall={})
768
+ def generate_extras(options, recall = {})
656
769
  route_key = options.delete :use_route
657
770
  path, params = generate(route_key, options, recall)
658
771
  return path, params.keys
@@ -672,7 +785,7 @@ module ActionDispatch
672
785
  end
673
786
 
674
787
  def find_script_name(options)
675
- options.delete(:script_name) || find_relative_url_root(options) || ''
788
+ options.delete(:script_name) || find_relative_url_root(options) || ""
676
789
  end
677
790
 
678
791
  def find_relative_url_root(options)
@@ -694,7 +807,7 @@ module ActionDispatch
694
807
  password = options.delete :password
695
808
  end
696
809
 
697
- recall = options.delete(:_recall) { {} }
810
+ recall = options.delete(:_recall) { {} }
698
811
 
699
812
  original_script_name = options.delete(:original_script_name)
700
813
  script_name = find_script_name options
@@ -733,7 +846,7 @@ module ActionDispatch
733
846
  extras = environment[:extras] || {}
734
847
 
735
848
  begin
736
- env = Rack::MockRequest.env_for(path, {:method => method})
849
+ env = Rack::MockRequest.env_for(path, method: method)
737
850
  rescue URI::InvalidURIError => e
738
851
  raise ActionController::RoutingError, e.message
739
852
  end
@@ -747,7 +860,8 @@ module ActionDispatch
747
860
  params[key] = URI.parser.unescape(value)
748
861
  end
749
862
  end
750
- req.path_parameters = params
863
+ old_params = req.path_parameters
864
+ req.path_parameters = old_params.merge params
751
865
  app = route.app
752
866
  if app.matches?(req) && app.dispatcher?
753
867
  begin