actionpack 5.2.4.4 → 6.1.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +264 -322
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -3
  5. data/lib/abstract_controller.rb +1 -0
  6. data/lib/abstract_controller/base.rb +38 -4
  7. data/lib/abstract_controller/caching.rb +1 -1
  8. data/lib/abstract_controller/caching/fragments.rb +6 -22
  9. data/lib/abstract_controller/callbacks.rb +14 -2
  10. data/lib/abstract_controller/collector.rb +1 -2
  11. data/lib/abstract_controller/helpers.rb +106 -90
  12. data/lib/abstract_controller/railties/routes_helpers.rb +1 -1
  13. data/lib/abstract_controller/rendering.rb +9 -9
  14. data/lib/abstract_controller/translation.rb +11 -5
  15. data/lib/action_controller.rb +7 -4
  16. data/lib/action_controller/api.rb +4 -3
  17. data/lib/action_controller/base.rb +6 -9
  18. data/lib/action_controller/caching.rb +1 -3
  19. data/lib/action_controller/log_subscriber.rb +10 -7
  20. data/lib/action_controller/metal.rb +10 -8
  21. data/lib/action_controller/metal/basic_implicit_render.rb +1 -1
  22. data/lib/action_controller/metal/conditional_get.rb +19 -5
  23. data/lib/action_controller/metal/content_security_policy.rb +1 -2
  24. data/lib/action_controller/metal/cookies.rb +3 -1
  25. data/lib/action_controller/metal/data_streaming.rb +6 -7
  26. data/lib/action_controller/metal/default_headers.rb +17 -0
  27. data/lib/action_controller/metal/etag_with_template_digest.rb +3 -5
  28. data/lib/action_controller/metal/exceptions.rb +56 -2
  29. data/lib/action_controller/metal/flash.rb +5 -5
  30. data/lib/action_controller/metal/head.rb +7 -4
  31. data/lib/action_controller/metal/helpers.rb +14 -5
  32. data/lib/action_controller/metal/http_authentication.rb +24 -23
  33. data/lib/action_controller/metal/implicit_render.rb +5 -15
  34. data/lib/action_controller/metal/instrumentation.rb +13 -14
  35. data/lib/action_controller/metal/live.rb +30 -32
  36. data/lib/action_controller/metal/logging.rb +20 -0
  37. data/lib/action_controller/metal/mime_responds.rb +19 -4
  38. data/lib/action_controller/metal/parameter_encoding.rb +35 -4
  39. data/lib/action_controller/metal/params_wrapper.rb +31 -22
  40. data/lib/action_controller/metal/permissions_policy.rb +46 -0
  41. data/lib/action_controller/metal/redirecting.rb +6 -6
  42. data/lib/action_controller/metal/renderers.rb +4 -4
  43. data/lib/action_controller/metal/rendering.rb +8 -3
  44. data/lib/action_controller/metal/request_forgery_protection.rb +62 -34
  45. data/lib/action_controller/metal/rescue.rb +1 -1
  46. data/lib/action_controller/metal/streaming.rb +0 -1
  47. data/lib/action_controller/metal/strong_parameters.rb +167 -58
  48. data/lib/action_controller/metal/url_for.rb +1 -1
  49. data/lib/action_controller/railties/helpers.rb +1 -1
  50. data/lib/action_controller/renderer.rb +37 -13
  51. data/lib/action_controller/template_assertions.rb +1 -1
  52. data/lib/action_controller/test_case.rb +70 -65
  53. data/lib/action_dispatch.rb +9 -3
  54. data/lib/action_dispatch/http/cache.rb +26 -21
  55. data/lib/action_dispatch/http/content_disposition.rb +45 -0
  56. data/lib/action_dispatch/http/content_security_policy.rb +33 -19
  57. data/lib/action_dispatch/http/filter_parameters.rb +9 -8
  58. data/lib/action_dispatch/http/filter_redirect.rb +2 -3
  59. data/lib/action_dispatch/http/headers.rb +4 -4
  60. data/lib/action_dispatch/http/mime_negotiation.rb +26 -13
  61. data/lib/action_dispatch/http/mime_type.rb +42 -23
  62. data/lib/action_dispatch/http/parameters.rb +14 -23
  63. data/lib/action_dispatch/http/permissions_policy.rb +173 -0
  64. data/lib/action_dispatch/http/request.rb +45 -22
  65. data/lib/action_dispatch/http/response.rb +45 -25
  66. data/lib/action_dispatch/http/upload.rb +9 -1
  67. data/lib/action_dispatch/http/url.rb +82 -82
  68. data/lib/action_dispatch/journey.rb +0 -2
  69. data/lib/action_dispatch/journey/formatter.rb +54 -30
  70. data/lib/action_dispatch/journey/gtg/builder.rb +22 -37
  71. data/lib/action_dispatch/journey/gtg/simulator.rb +8 -7
  72. data/lib/action_dispatch/journey/gtg/transition_table.rb +6 -5
  73. data/lib/action_dispatch/journey/nfa/dot.rb +0 -11
  74. data/lib/action_dispatch/journey/nodes/node.rb +13 -11
  75. data/lib/action_dispatch/journey/parser.rb +13 -13
  76. data/lib/action_dispatch/journey/parser.y +1 -1
  77. data/lib/action_dispatch/journey/path/pattern.rb +19 -21
  78. data/lib/action_dispatch/journey/route.rb +10 -20
  79. data/lib/action_dispatch/journey/router.rb +26 -34
  80. data/lib/action_dispatch/journey/router/utils.rb +14 -12
  81. data/lib/action_dispatch/journey/routes.rb +0 -2
  82. data/lib/action_dispatch/journey/scanner.rb +10 -4
  83. data/lib/action_dispatch/journey/visitors.rb +1 -4
  84. data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
  85. data/lib/action_dispatch/middleware/callbacks.rb +2 -4
  86. data/lib/action_dispatch/middleware/cookies.rb +128 -109
  87. data/lib/action_dispatch/middleware/debug_exceptions.rb +43 -66
  88. data/lib/action_dispatch/middleware/debug_locks.rb +5 -5
  89. data/lib/action_dispatch/middleware/debug_view.rb +66 -0
  90. data/lib/action_dispatch/middleware/exception_wrapper.rb +75 -30
  91. data/lib/action_dispatch/middleware/flash.rb +1 -1
  92. data/lib/action_dispatch/middleware/host_authorization.rb +121 -0
  93. data/lib/action_dispatch/middleware/public_exceptions.rb +6 -3
  94. data/lib/action_dispatch/middleware/remote_ip.rb +14 -16
  95. data/lib/action_dispatch/middleware/request_id.rb +5 -6
  96. data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -3
  97. data/lib/action_dispatch/middleware/session/cookie_store.rb +3 -9
  98. data/lib/action_dispatch/middleware/show_exceptions.rb +3 -2
  99. data/lib/action_dispatch/middleware/ssl.rb +20 -15
  100. data/lib/action_dispatch/middleware/stack.rb +56 -2
  101. data/lib/action_dispatch/middleware/static.rb +153 -93
  102. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  103. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  104. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
  105. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +3 -1
  106. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  107. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +4 -2
  108. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +45 -35
  109. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
  110. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
  111. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +23 -4
  112. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
  113. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +6 -3
  114. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +3 -1
  115. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +104 -8
  116. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
  117. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  118. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +2 -2
  119. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -1
  120. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +2 -2
  121. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
  122. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +24 -1
  123. data/lib/action_dispatch/railtie.rb +8 -2
  124. data/lib/action_dispatch/request/session.rb +10 -9
  125. data/lib/action_dispatch/request/utils.rb +26 -2
  126. data/lib/action_dispatch/routing.rb +21 -20
  127. data/lib/action_dispatch/routing/inspector.rb +100 -52
  128. data/lib/action_dispatch/routing/mapper.rb +155 -103
  129. data/lib/action_dispatch/routing/polymorphic_routes.rb +13 -15
  130. data/lib/action_dispatch/routing/redirection.rb +3 -3
  131. data/lib/action_dispatch/routing/route_set.rb +71 -69
  132. data/lib/action_dispatch/routing/url_for.rb +2 -2
  133. data/lib/action_dispatch/system_test_case.rb +54 -11
  134. data/lib/action_dispatch/system_testing/browser.rb +53 -16
  135. data/lib/action_dispatch/system_testing/driver.rb +11 -3
  136. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +49 -7
  137. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +8 -10
  138. data/lib/action_dispatch/testing/assertion_response.rb +0 -1
  139. data/lib/action_dispatch/testing/assertions.rb +1 -1
  140. data/lib/action_dispatch/testing/assertions/response.rb +4 -7
  141. data/lib/action_dispatch/testing/assertions/routing.rb +20 -8
  142. data/lib/action_dispatch/testing/integration.rb +61 -28
  143. data/lib/action_dispatch/testing/request_encoder.rb +2 -2
  144. data/lib/action_dispatch/testing/test_process.rb +29 -4
  145. data/lib/action_dispatch/testing/test_request.rb +3 -3
  146. data/lib/action_dispatch/testing/test_response.rb +4 -32
  147. data/lib/action_pack.rb +1 -1
  148. data/lib/action_pack/gem_version.rb +4 -4
  149. metadata +38 -26
  150. data/lib/action_controller/metal/force_ssl.rb +0 -99
  151. data/lib/action_dispatch/http/parameter_filter.rb +0 -86
  152. data/lib/action_dispatch/journey/nfa/builder.rb +0 -78
  153. data/lib/action_dispatch/journey/nfa/simulator.rb +0 -49
  154. data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -120
  155. data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +0 -26
@@ -120,8 +120,7 @@ module ActionDispatch
120
120
  opts
121
121
  end
122
122
 
123
- # Returns the path component of a URL for the given record. It uses
124
- # <tt>polymorphic_url</tt> with <tt>routing_type: :path</tt>.
123
+ # Returns the path component of a URL for the given record.
125
124
  def polymorphic_path(record_or_hash_or_array, options = {})
126
125
  if Hash === record_or_hash_or_array
127
126
  options = record_or_hash_or_array.merge(options)
@@ -146,6 +145,7 @@ module ActionDispatch
146
145
 
147
146
  %w(edit new).each do |action|
148
147
  module_eval <<-EOT, __FILE__, __LINE__ + 1
148
+ # frozen_string_literal: true
149
149
  def #{action}_polymorphic_url(record_or_hash, options = {})
150
150
  polymorphic_url_for_action("#{action}", record_or_hash, options)
151
151
  end
@@ -157,7 +157,6 @@ module ActionDispatch
157
157
  end
158
158
 
159
159
  private
160
-
161
160
  def polymorphic_url_for_action(action, record_or_hash, options)
162
161
  polymorphic_url(record_or_hash, options.merge(action: action))
163
162
  end
@@ -175,15 +174,15 @@ module ActionDispatch
175
174
  end
176
175
 
177
176
  class HelperMethodBuilder # :nodoc:
178
- CACHE = { "path" => {}, "url" => {} }
177
+ CACHE = { path: {}, url: {} }
179
178
 
180
179
  def self.get(action, type)
181
- type = type.to_s
180
+ type = type.to_sym
182
181
  CACHE[type].fetch(action) { build action, type }
183
182
  end
184
183
 
185
- def self.url; CACHE["url".freeze][nil]; end
186
- def self.path; CACHE["path".freeze][nil]; end
184
+ def self.url; CACHE[:url][nil]; end
185
+ def self.path; CACHE[:path][nil]; end
187
186
 
188
187
  def self.build(action, type)
189
188
  prefix = action ? "#{action}_" : ""
@@ -229,9 +228,9 @@ module ActionDispatch
229
228
  end
230
229
 
231
230
  if options.empty?
232
- recipient.send(method, *args)
231
+ recipient.public_send(method, *args)
233
232
  else
234
- recipient.send(method, *args, options)
233
+ recipient.public_send(method, *args, options)
235
234
  end
236
235
  end
237
236
 
@@ -248,7 +247,7 @@ module ActionDispatch
248
247
  end
249
248
 
250
249
  def handle_string_call(target, str)
251
- target.send get_method_for_string str
250
+ target.public_send get_method_for_string str
252
251
  end
253
252
 
254
253
  def handle_class(klass)
@@ -256,7 +255,7 @@ module ActionDispatch
256
255
  end
257
256
 
258
257
  def handle_class_call(target, klass)
259
- target.send get_method_for_class klass
258
+ target.public_send get_method_for_class klass
260
259
  end
261
260
 
262
261
  def handle_model(record)
@@ -278,7 +277,7 @@ module ActionDispatch
278
277
  mapping.call(target, [record], suffix == "path")
279
278
  else
280
279
  method, args = handle_model(record)
281
- target.send(method, *args)
280
+ target.public_send(method, *args)
282
281
  end
283
282
  end
284
283
 
@@ -324,7 +323,6 @@ module ActionDispatch
324
323
  end
325
324
 
326
325
  private
327
-
328
326
  def polymorphic_mapping(target, record)
329
327
  if record.respond_to?(:to_model)
330
328
  target._routes.polymorphic_mappings[record.to_model.model_name.name]
@@ -343,8 +341,8 @@ module ActionDispatch
343
341
  end
344
342
 
345
343
  [nil, "new", "edit"].each do |action|
346
- CACHE["url"][action] = build action, "url"
347
- CACHE["path"][action] = build action, "path"
344
+ CACHE[:url][action] = build action, "url"
345
+ CACHE[:path][action] = build action, "path"
348
346
  end
349
347
  end
350
348
  end
@@ -65,15 +65,15 @@ module ActionDispatch
65
65
  end
66
66
 
67
67
  def escape(params)
68
- Hash[params.map { |k, v| [k, Rack::Utils.escape(v)] }]
68
+ params.transform_values { |v| Rack::Utils.escape(v) }
69
69
  end
70
70
 
71
71
  def escape_fragment(params)
72
- Hash[params.map { |k, v| [k, Journey::Router::Utils.escape_fragment(v)] }]
72
+ params.transform_values { |v| Journey::Router::Utils.escape_fragment(v) }
73
73
  end
74
74
 
75
75
  def escape_path(params)
76
- Hash[params.map { |k, v| [k, Journey::Router::Utils.escape_path(v)] }]
76
+ params.transform_values { |v| Journey::Router::Utils.escape_path(v) }
77
77
  end
78
78
  end
79
79
 
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "action_dispatch/journey"
4
4
  require "active_support/core_ext/object/to_query"
5
- require "active_support/core_ext/hash/slice"
6
5
  require "active_support/core_ext/module/redefine_method"
7
6
  require "active_support/core_ext/module/remove_method"
8
7
  require "active_support/core_ext/array/extract_options"
@@ -36,12 +35,11 @@ module ActionDispatch
36
35
  if @raise_on_name_error
37
36
  raise
38
37
  else
39
- return [404, { "X-Cascade" => "pass" }, []]
38
+ [404, { "X-Cascade" => "pass" }, []]
40
39
  end
41
40
  end
42
41
 
43
42
  private
44
-
45
43
  def controller(req)
46
44
  req.controller_class
47
45
  rescue NameError => e
@@ -60,7 +58,6 @@ module ActionDispatch
60
58
  end
61
59
 
62
60
  private
63
-
64
61
  def controller(_); @controller_class; end
65
62
  end
66
63
 
@@ -91,11 +88,11 @@ module ActionDispatch
91
88
 
92
89
  def clear!
93
90
  @path_helpers.each do |helper|
94
- @path_helpers_module.send :remove_method, helper
91
+ @path_helpers_module.remove_method helper
95
92
  end
96
93
 
97
94
  @url_helpers.each do |helper|
98
- @url_helpers_module.send :remove_method, helper
95
+ @url_helpers_module.remove_method helper
99
96
  end
100
97
 
101
98
  @routes.clear
@@ -109,12 +106,14 @@ module ActionDispatch
109
106
  url_name = :"#{name}_url"
110
107
 
111
108
  if routes.key? key
112
- @path_helpers_module.send :undef_method, path_name
113
- @url_helpers_module.send :undef_method, url_name
109
+ @path_helpers_module.undef_method path_name
110
+ @url_helpers_module.undef_method url_name
114
111
  end
115
112
  routes[key] = route
116
- define_url_helper @path_helpers_module, route, path_name, route.defaults, name, PATH
117
- define_url_helper @url_helpers_module, route, url_name, route.defaults, name, UNKNOWN
113
+
114
+ helper = UrlHelper.create(route, route.defaults, name)
115
+ define_url_helper @path_helpers_module, path_name, helper, PATH
116
+ define_url_helper @url_helpers_module, url_name, helper, UNKNOWN
118
117
 
119
118
  @path_helpers << path_name
120
119
  @url_helpers << url_name
@@ -154,13 +153,13 @@ module ActionDispatch
154
153
  url_name = :"#{name}_url"
155
154
 
156
155
  @path_helpers_module.module_eval do
157
- define_method(path_name) do |*args|
156
+ redefine_method(path_name) do |*args|
158
157
  helper.call(self, args, true)
159
158
  end
160
159
  end
161
160
 
162
161
  @url_helpers_module.module_eval do
163
- define_method(url_name) do |*args|
162
+ redefine_method(url_name) do |*args|
164
163
  helper.call(self, args, false)
165
164
  end
166
165
  end
@@ -172,30 +171,30 @@ module ActionDispatch
172
171
  end
173
172
 
174
173
  class UrlHelper
175
- def self.create(route, options, route_name, url_strategy)
174
+ def self.create(route, options, route_name)
176
175
  if optimize_helper?(route)
177
- OptimizedUrlHelper.new(route, options, route_name, url_strategy)
176
+ OptimizedUrlHelper.new(route, options, route_name)
178
177
  else
179
- new route, options, route_name, url_strategy
178
+ new(route, options, route_name)
180
179
  end
181
180
  end
182
181
 
183
182
  def self.optimize_helper?(route)
184
- !route.glob? && route.path.requirements.empty?
183
+ route.path.requirements.empty? && !route.glob?
185
184
  end
186
185
 
187
- attr_reader :url_strategy, :route_name
186
+ attr_reader :route_name
188
187
 
189
188
  class OptimizedUrlHelper < UrlHelper
190
189
  attr_reader :arg_size
191
190
 
192
- def initialize(route, options, route_name, url_strategy)
191
+ def initialize(route, options, route_name)
193
192
  super
194
193
  @required_parts = @route.required_parts
195
194
  @arg_size = @required_parts.size
196
195
  end
197
196
 
198
- def call(t, args, inner_options)
197
+ def call(t, method_name, args, inner_options, url_strategy)
199
198
  if args.size == arg_size && !inner_options && optimize_routes_generation?(t)
200
199
  options = t.url_options.merge @options
201
200
  options[:path] = optimized_helper(args)
@@ -216,7 +215,6 @@ module ActionDispatch
216
215
  end
217
216
 
218
217
  private
219
-
220
218
  def optimized_helper(args)
221
219
  params = parameterize_args(args) do
222
220
  raise_generation_error(args)
@@ -246,22 +244,21 @@ module ActionDispatch
246
244
  missing_keys << missing_key
247
245
  }
248
246
  constraints = Hash[@route.requirements.merge(params).sort_by { |k, v| k.to_s }]
249
- message = "No route matches #{constraints.inspect}".dup
247
+ message = +"No route matches #{constraints.inspect}"
250
248
  message << ", missing required keys: #{missing_keys.sort.inspect}"
251
249
 
252
250
  raise ActionController::UrlGenerationError, message
253
251
  end
254
252
  end
255
253
 
256
- def initialize(route, options, route_name, url_strategy)
254
+ def initialize(route, options, route_name)
257
255
  @options = options
258
256
  @segment_keys = route.segment_keys.uniq
259
257
  @route = route
260
- @url_strategy = url_strategy
261
258
  @route_name = route_name
262
259
  end
263
260
 
264
- def call(t, args, inner_options)
261
+ def call(t, method_name, args, inner_options, url_strategy)
265
262
  controller_options = t.url_options
266
263
  options = controller_options.merge @options
267
264
  hash = handle_positional_args(controller_options,
@@ -270,7 +267,7 @@ module ActionDispatch
270
267
  options,
271
268
  @segment_keys)
272
269
 
273
- t._routes.url_for(hash, route_name, url_strategy)
270
+ t._routes.url_for(hash, route_name, url_strategy, method_name)
274
271
  end
275
272
 
276
273
  def handle_positional_args(controller_options, inner_options, args, result, path_params)
@@ -316,31 +313,28 @@ module ActionDispatch
316
313
  #
317
314
  # foo_url(bar, baz, bang, sort_by: 'baz')
318
315
  #
319
- def define_url_helper(mod, route, name, opts, route_key, url_strategy)
320
- helper = UrlHelper.create(route, opts, route_key, url_strategy)
321
- mod.module_eval do
322
- define_method(name) do |*args|
323
- last = args.last
324
- options = \
325
- case last
326
- when Hash
327
- args.pop
328
- when ActionController::Parameters
329
- args.pop.to_h
330
- end
331
- helper.call self, args, options
332
- end
316
+ def define_url_helper(mod, name, helper, url_strategy)
317
+ mod.define_method(name) do |*args|
318
+ last = args.last
319
+ options = \
320
+ case last
321
+ when Hash
322
+ args.pop
323
+ when ActionController::Parameters
324
+ args.pop.to_h
325
+ end
326
+ helper.call(self, name, args, options, url_strategy)
333
327
  end
334
328
  end
335
329
  end
336
330
 
337
- # strategy for building urls to send to the client
331
+ # strategy for building URLs to send to the client
338
332
  PATH = ->(options) { ActionDispatch::Http::URL.path_for(options) }
339
333
  UNKNOWN = ->(options) { ActionDispatch::Http::URL.url_for(options) }
340
334
 
341
335
  attr_accessor :formatter, :set, :named_routes, :default_scope, :router
342
336
  attr_accessor :disable_clear_and_finalize, :resources_path_names
343
- attr_accessor :default_url_options
337
+ attr_accessor :default_url_options, :draw_paths
344
338
  attr_reader :env_key, :polymorphic_mappings
345
339
 
346
340
  alias :routes :set
@@ -372,13 +366,14 @@ module ActionDispatch
372
366
  self.named_routes = NamedRouteCollection.new
373
367
  self.resources_path_names = self.class.default_resources_path_names
374
368
  self.default_url_options = {}
369
+ self.draw_paths = []
375
370
 
376
371
  @config = config
377
372
  @append = []
378
373
  @prepend = []
379
374
  @disable_clear_and_finalize = false
380
375
  @finalized = false
381
- @env_key = "ROUTES_#{object_id}_SCRIPT_NAME".freeze
376
+ @env_key = "ROUTES_#{object_id}_SCRIPT_NAME"
382
377
 
383
378
  @set = Journey::Routes.new
384
379
  @router = Journey::Router.new @set
@@ -482,6 +477,14 @@ module ActionDispatch
482
477
  end
483
478
 
484
479
  def url_helpers(supports_path = true)
480
+ if supports_path
481
+ @url_helpers_with_paths ||= generate_url_helpers(true)
482
+ else
483
+ @url_helpers_without_paths ||= generate_url_helpers(false)
484
+ end
485
+ end
486
+
487
+ def generate_url_helpers(supports_path)
485
488
  routes = self
486
489
 
487
490
  Module.new do
@@ -585,7 +588,7 @@ module ActionDispatch
585
588
  "You may have defined two routes with the same name using the `:as` option, or " \
586
589
  "you may be overriding a route already defined by a resource with the same naming. " \
587
590
  "For the latter, you can restrict the routes created with `resources` as explained here: \n" \
588
- "http://guides.rubyonrails.org/routing.html#restricting-the-routes-created"
591
+ "https://guides.rubyonrails.org/routing.html#restricting-the-routes-created"
589
592
  end
590
593
 
591
594
  route = @set.add_route(name, mapping)
@@ -594,14 +597,14 @@ module ActionDispatch
594
597
  if route.segment_keys.include?(:controller)
595
598
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
596
599
  Using a dynamic :controller segment in a route is deprecated and
597
- will be removed in Rails 6.0.
600
+ will be removed in Rails 6.2.
598
601
  MSG
599
602
  end
600
603
 
601
604
  if route.segment_keys.include?(:action)
602
605
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
603
606
  Using a dynamic :action segment in a route is deprecated and
604
- will be removed in Rails 6.0.
607
+ will be removed in Rails 6.2.
605
608
  MSG
606
609
  end
607
610
 
@@ -647,14 +650,6 @@ module ActionDispatch
647
650
  end
648
651
 
649
652
  class Generator
650
- PARAMETERIZE = lambda do |name, value|
651
- if name == :controller
652
- value
653
- else
654
- value.to_param
655
- end
656
- end
657
-
658
653
  attr_reader :options, :recall, :set, :named_route
659
654
 
660
655
  def initialize(named_route, options, recall, set)
@@ -730,7 +725,7 @@ module ActionDispatch
730
725
  # Remove leading slashes from controllers
731
726
  def normalize_controller!
732
727
  if controller
733
- if controller.start_with?("/".freeze)
728
+ if controller.start_with?("/")
734
729
  @options[:controller] = controller[1..-1]
735
730
  else
736
731
  @options[:controller] = controller
@@ -738,10 +733,10 @@ module ActionDispatch
738
733
  end
739
734
  end
740
735
 
741
- # Generates a path from routes, returns [path, params].
742
- # If no route is generated the formatter will raise ActionController::UrlGenerationError
736
+ # Generates a path from routes, returns a RouteWithParams or MissingRoute.
737
+ # MissingRoute will raise ActionController::UrlGenerationError.
743
738
  def generate
744
- @set.formatter.generate(named_route, options, recall, PARAMETERIZE)
739
+ @set.formatter.generate(named_route, options, recall)
745
740
  end
746
741
 
747
742
  def different_controller?
@@ -766,13 +761,18 @@ module ActionDispatch
766
761
  end
767
762
 
768
763
  def generate_extras(options, recall = {})
769
- route_key = options.delete :use_route
770
- path, params = generate(route_key, options, recall)
771
- return path, params.keys
764
+ if recall
765
+ options = options.merge(_recall: recall)
766
+ end
767
+
768
+ route_name = options.delete :use_route
769
+ generator = generate(route_name, options, recall)
770
+ path_info = path_for(options, route_name, [])
771
+ [URI(path_info).path, generator.params.except(:_recall).keys]
772
772
  end
773
773
 
774
- def generate(route_key, options, recall = {})
775
- Generator.new(route_key, options, recall, self).generate
774
+ def generate(route_name, options, recall = {}, method_name = nil)
775
+ Generator.new(route_name, options, recall, self).generate
776
776
  end
777
777
  private :generate
778
778
 
@@ -792,12 +792,12 @@ module ActionDispatch
792
792
  options.delete(:relative_url_root) || relative_url_root
793
793
  end
794
794
 
795
- def path_for(options, route_name = nil)
796
- url_for(options, route_name, PATH)
795
+ def path_for(options, route_name = nil, reserved = RESERVED_OPTIONS)
796
+ url_for(options, route_name, PATH, nil, reserved)
797
797
  end
798
798
 
799
799
  # The +options+ argument must be a hash whose keys are *symbols*.
800
- def url_for(options, route_name = nil, url_strategy = UNKNOWN)
800
+ def url_for(options, route_name = nil, url_strategy = UNKNOWN, method_name = nil, reserved = RESERVED_OPTIONS)
801
801
  options = default_url_options.merge options
802
802
 
803
803
  user = password = nil
@@ -817,9 +817,11 @@ module ActionDispatch
817
817
  end
818
818
 
819
819
  path_options = options.dup
820
- RESERVED_OPTIONS.each { |ro| path_options.delete ro }
820
+ reserved.each { |ro| path_options.delete ro }
821
821
 
822
- path, params = generate(route_name, path_options, recall)
822
+ route_with_params = generate(route_name, path_options, recall)
823
+ path = route_with_params.path(method_name)
824
+ params = route_with_params.params
823
825
 
824
826
  if options.key? :params
825
827
  params.merge! options[:params]
@@ -842,7 +844,7 @@ module ActionDispatch
842
844
 
843
845
  def recognize_path(path, environment = {})
844
846
  method = (environment[:method] || "GET").to_s.upcase
845
- path = Journey::Router::Utils.normalize_path(path) unless path =~ %r{://}
847
+ path = Journey::Router::Utils.normalize_path(path) unless %r{://}.match?(path)
846
848
  extras = environment[:extras] || {}
847
849
 
848
850
  begin
@@ -861,7 +863,7 @@ module ActionDispatch
861
863
  params.each do |key, value|
862
864
  if value.is_a?(String)
863
865
  value = value.dup.force_encoding(Encoding::BINARY)
864
- params[key] = URI.parser.unescape(value)
866
+ params[key] = URI::DEFAULT_PARSER.unescape(value)
865
867
  end
866
868
  end
867
869
  req.path_parameters = params