actionpack 7.0.8.1 → 7.2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +94 -500
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -2
  5. data/lib/abstract_controller/asset_paths.rb +2 -0
  6. data/lib/abstract_controller/base.rb +119 -106
  7. data/lib/abstract_controller/caching/fragments.rb +51 -52
  8. data/lib/abstract_controller/caching.rb +2 -0
  9. data/lib/abstract_controller/callbacks.rb +94 -67
  10. data/lib/abstract_controller/collector.rb +6 -6
  11. data/lib/abstract_controller/deprecator.rb +9 -0
  12. data/lib/abstract_controller/error.rb +2 -0
  13. data/lib/abstract_controller/helpers.rb +121 -91
  14. data/lib/abstract_controller/logger.rb +2 -0
  15. data/lib/abstract_controller/railties/routes_helpers.rb +3 -16
  16. data/lib/abstract_controller/rendering.rb +14 -13
  17. data/lib/abstract_controller/translation.rb +12 -30
  18. data/lib/abstract_controller/url_for.rb +9 -5
  19. data/lib/abstract_controller.rb +8 -0
  20. data/lib/action_controller/api/api_rendering.rb +2 -0
  21. data/lib/action_controller/api.rb +78 -73
  22. data/lib/action_controller/base.rb +199 -141
  23. data/lib/action_controller/caching.rb +16 -11
  24. data/lib/action_controller/deprecator.rb +9 -0
  25. data/lib/action_controller/form_builder.rb +21 -16
  26. data/lib/action_controller/log_subscriber.rb +19 -5
  27. data/lib/action_controller/metal/allow_browser.rb +123 -0
  28. data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
  29. data/lib/action_controller/metal/conditional_get.rb +187 -174
  30. data/lib/action_controller/metal/content_security_policy.rb +26 -25
  31. data/lib/action_controller/metal/cookies.rb +4 -2
  32. data/lib/action_controller/metal/data_streaming.rb +65 -54
  33. data/lib/action_controller/metal/default_headers.rb +6 -2
  34. data/lib/action_controller/metal/etag_with_flash.rb +4 -0
  35. data/lib/action_controller/metal/etag_with_template_digest.rb +18 -14
  36. data/lib/action_controller/metal/exceptions.rb +19 -9
  37. data/lib/action_controller/metal/flash.rb +12 -10
  38. data/lib/action_controller/metal/head.rb +20 -16
  39. data/lib/action_controller/metal/helpers.rb +64 -67
  40. data/lib/action_controller/metal/http_authentication.rb +214 -200
  41. data/lib/action_controller/metal/implicit_render.rb +21 -17
  42. data/lib/action_controller/metal/instrumentation.rb +22 -12
  43. data/lib/action_controller/metal/live.rb +125 -92
  44. data/lib/action_controller/metal/logging.rb +6 -4
  45. data/lib/action_controller/metal/mime_responds.rb +151 -142
  46. data/lib/action_controller/metal/parameter_encoding.rb +34 -32
  47. data/lib/action_controller/metal/params_wrapper.rb +58 -58
  48. data/lib/action_controller/metal/permissions_policy.rb +14 -13
  49. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  50. data/lib/action_controller/metal/redirecting.rb +110 -84
  51. data/lib/action_controller/metal/renderers.rb +50 -49
  52. data/lib/action_controller/metal/rendering.rb +103 -82
  53. data/lib/action_controller/metal/request_forgery_protection.rb +279 -161
  54. data/lib/action_controller/metal/rescue.rb +12 -8
  55. data/lib/action_controller/metal/streaming.rb +174 -132
  56. data/lib/action_controller/metal/strong_parameters.rb +598 -473
  57. data/lib/action_controller/metal/testing.rb +2 -0
  58. data/lib/action_controller/metal/url_for.rb +23 -14
  59. data/lib/action_controller/metal.rb +145 -61
  60. data/lib/action_controller/railtie.rb +25 -9
  61. data/lib/action_controller/railties/helpers.rb +2 -0
  62. data/lib/action_controller/renderer.rb +105 -66
  63. data/lib/action_controller/template_assertions.rb +4 -2
  64. data/lib/action_controller/test_case.rb +157 -128
  65. data/lib/action_controller.rb +17 -3
  66. data/lib/action_dispatch/constants.rb +34 -0
  67. data/lib/action_dispatch/deprecator.rb +9 -0
  68. data/lib/action_dispatch/http/cache.rb +28 -29
  69. data/lib/action_dispatch/http/content_disposition.rb +2 -0
  70. data/lib/action_dispatch/http/content_security_policy.rb +69 -49
  71. data/lib/action_dispatch/http/filter_parameters.rb +27 -12
  72. data/lib/action_dispatch/http/filter_redirect.rb +22 -1
  73. data/lib/action_dispatch/http/headers.rb +23 -21
  74. data/lib/action_dispatch/http/mime_negotiation.rb +37 -48
  75. data/lib/action_dispatch/http/mime_type.rb +60 -30
  76. data/lib/action_dispatch/http/mime_types.rb +5 -1
  77. data/lib/action_dispatch/http/parameters.rb +12 -10
  78. data/lib/action_dispatch/http/permissions_policy.rb +32 -34
  79. data/lib/action_dispatch/http/rack_cache.rb +4 -0
  80. data/lib/action_dispatch/http/request.rb +132 -79
  81. data/lib/action_dispatch/http/response.rb +136 -103
  82. data/lib/action_dispatch/http/upload.rb +19 -15
  83. data/lib/action_dispatch/http/url.rb +75 -73
  84. data/lib/action_dispatch/journey/formatter.rb +19 -6
  85. data/lib/action_dispatch/journey/gtg/builder.rb +4 -3
  86. data/lib/action_dispatch/journey/gtg/simulator.rb +2 -0
  87. data/lib/action_dispatch/journey/gtg/transition_table.rb +10 -8
  88. data/lib/action_dispatch/journey/nfa/dot.rb +2 -0
  89. data/lib/action_dispatch/journey/nodes/node.rb +6 -5
  90. data/lib/action_dispatch/journey/parser.rb +4 -3
  91. data/lib/action_dispatch/journey/parser_extras.rb +2 -0
  92. data/lib/action_dispatch/journey/path/pattern.rb +18 -15
  93. data/lib/action_dispatch/journey/route.rb +12 -9
  94. data/lib/action_dispatch/journey/router/utils.rb +16 -15
  95. data/lib/action_dispatch/journey/router.rb +13 -10
  96. data/lib/action_dispatch/journey/routes.rb +6 -4
  97. data/lib/action_dispatch/journey/scanner.rb +4 -2
  98. data/lib/action_dispatch/journey/visitors.rb +2 -0
  99. data/lib/action_dispatch/journey.rb +2 -0
  100. data/lib/action_dispatch/log_subscriber.rb +25 -0
  101. data/lib/action_dispatch/middleware/actionable_exceptions.rb +7 -6
  102. data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
  103. data/lib/action_dispatch/middleware/callbacks.rb +4 -0
  104. data/lib/action_dispatch/middleware/cookies.rb +192 -194
  105. data/lib/action_dispatch/middleware/debug_exceptions.rb +36 -27
  106. data/lib/action_dispatch/middleware/debug_locks.rb +18 -13
  107. data/lib/action_dispatch/middleware/debug_view.rb +9 -2
  108. data/lib/action_dispatch/middleware/exception_wrapper.rb +181 -27
  109. data/lib/action_dispatch/middleware/executor.rb +9 -1
  110. data/lib/action_dispatch/middleware/flash.rb +65 -46
  111. data/lib/action_dispatch/middleware/host_authorization.rb +22 -17
  112. data/lib/action_dispatch/middleware/public_exceptions.rb +12 -8
  113. data/lib/action_dispatch/middleware/reloader.rb +9 -5
  114. data/lib/action_dispatch/middleware/remote_ip.rb +88 -83
  115. data/lib/action_dispatch/middleware/request_id.rb +15 -8
  116. data/lib/action_dispatch/middleware/server_timing.rb +8 -6
  117. data/lib/action_dispatch/middleware/session/abstract_store.rb +7 -0
  118. data/lib/action_dispatch/middleware/session/cache_store.rb +14 -7
  119. data/lib/action_dispatch/middleware/session/cookie_store.rb +32 -25
  120. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +9 -3
  121. data/lib/action_dispatch/middleware/show_exceptions.rb +42 -28
  122. data/lib/action_dispatch/middleware/ssl.rb +60 -45
  123. data/lib/action_dispatch/middleware/stack.rb +15 -9
  124. data/lib/action_dispatch/middleware/static.rb +40 -34
  125. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +2 -2
  126. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +4 -4
  127. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +8 -1
  128. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +7 -7
  129. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
  130. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +17 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +16 -12
  132. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -1
  133. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  134. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +4 -4
  135. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
  136. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
  137. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +3 -0
  138. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +47 -38
  139. data/lib/action_dispatch/railtie.rb +12 -4
  140. data/lib/action_dispatch/request/session.rb +39 -27
  141. data/lib/action_dispatch/request/utils.rb +10 -3
  142. data/lib/action_dispatch/routing/endpoint.rb +2 -0
  143. data/lib/action_dispatch/routing/inspector.rb +59 -9
  144. data/lib/action_dispatch/routing/mapper.rb +686 -639
  145. data/lib/action_dispatch/routing/polymorphic_routes.rb +70 -61
  146. data/lib/action_dispatch/routing/redirection.rb +52 -38
  147. data/lib/action_dispatch/routing/route_set.rb +106 -62
  148. data/lib/action_dispatch/routing/routes_proxy.rb +16 -19
  149. data/lib/action_dispatch/routing/url_for.rb +131 -122
  150. data/lib/action_dispatch/routing.rb +152 -150
  151. data/lib/action_dispatch/system_test_case.rb +91 -81
  152. data/lib/action_dispatch/system_testing/browser.rb +27 -19
  153. data/lib/action_dispatch/system_testing/driver.rb +16 -22
  154. data/lib/action_dispatch/system_testing/server.rb +2 -0
  155. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +53 -31
  156. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
  157. data/lib/action_dispatch/testing/assertion_response.rb +9 -7
  158. data/lib/action_dispatch/testing/assertions/response.rb +36 -26
  159. data/lib/action_dispatch/testing/assertions/routing.rb +203 -95
  160. data/lib/action_dispatch/testing/assertions.rb +5 -1
  161. data/lib/action_dispatch/testing/integration.rb +240 -229
  162. data/lib/action_dispatch/testing/request_encoder.rb +6 -1
  163. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  164. data/lib/action_dispatch/testing/test_process.rb +14 -9
  165. data/lib/action_dispatch/testing/test_request.rb +4 -2
  166. data/lib/action_dispatch/testing/test_response.rb +34 -19
  167. data/lib/action_dispatch.rb +52 -21
  168. data/lib/action_pack/gem_version.rb +5 -3
  169. data/lib/action_pack/version.rb +3 -1
  170. data/lib/action_pack.rb +18 -17
  171. metadata +91 -32
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/core_ext/module/attribute_accessors"
4
6
 
5
7
  module ActionDispatch
@@ -15,20 +17,20 @@ module ActionDispatch
15
17
  class << self
16
18
  # Returns the domain part of a host given the domain level.
17
19
  #
18
- # # Top-level domain example
19
- # extract_domain('www.example.com', 1) # => "example.com"
20
- # # Second-level domain example
21
- # extract_domain('dev.www.example.co.uk', 2) # => "example.co.uk"
20
+ # # Top-level domain example
21
+ # extract_domain('www.example.com', 1) # => "example.com"
22
+ # # Second-level domain example
23
+ # extract_domain('dev.www.example.co.uk', 2) # => "example.co.uk"
22
24
  def extract_domain(host, tld_length)
23
25
  extract_domain_from(host, tld_length) if named_host?(host)
24
26
  end
25
27
 
26
28
  # Returns the subdomains of a host as an Array given the domain level.
27
29
  #
28
- # # Top-level domain example
29
- # extract_subdomains('www.example.com', 1) # => ["www"]
30
- # # Second-level domain example
31
- # extract_subdomains('dev.www.example.co.uk', 2) # => ["dev", "www"]
30
+ # # Top-level domain example
31
+ # extract_subdomains('www.example.com', 1) # => ["www"]
32
+ # # Second-level domain example
33
+ # extract_subdomains('dev.www.example.co.uk', 2) # => ["dev", "www"]
32
34
  def extract_subdomains(host, tld_length)
33
35
  if named_host?(host)
34
36
  extract_subdomains_from(host, tld_length)
@@ -39,10 +41,10 @@ module ActionDispatch
39
41
 
40
42
  # Returns the subdomains of a host as a String given the domain level.
41
43
  #
42
- # # Top-level domain example
43
- # extract_subdomain('www.example.com', 1) # => "www"
44
- # # Second-level domain example
45
- # extract_subdomain('dev.www.example.co.uk', 2) # => "dev.www"
44
+ # # Top-level domain example
45
+ # extract_subdomain('www.example.com', 1) # => "www"
46
+ # # Second-level domain example
47
+ # extract_subdomain('dev.www.example.co.uk', 2) # => "dev.www"
46
48
  def extract_subdomain(host, tld_length)
47
49
  extract_subdomains(host, tld_length).join(".")
48
50
  end
@@ -184,33 +186,33 @@ module ActionDispatch
184
186
 
185
187
  # Returns the complete URL used for this request.
186
188
  #
187
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com'
188
- # req.url # => "http://example.com"
189
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com'
190
+ # req.url # => "http://example.com"
189
191
  def url
190
192
  protocol + host_with_port + fullpath
191
193
  end
192
194
 
193
195
  # Returns 'https://' if this is an SSL request and 'http://' otherwise.
194
196
  #
195
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com'
196
- # req.protocol # => "http://"
197
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com'
198
+ # req.protocol # => "http://"
197
199
  #
198
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com', 'HTTPS' => 'on'
199
- # req.protocol # => "https://"
200
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com', 'HTTPS' => 'on'
201
+ # req.protocol # => "https://"
200
202
  def protocol
201
203
  @protocol ||= ssl? ? "https://" : "http://"
202
204
  end
203
205
 
204
- # Returns the \host and port for this request, such as "example.com:8080".
206
+ # Returns the host and port for this request, such as "example.com:8080".
205
207
  #
206
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com'
207
- # req.raw_host_with_port # => "example.com"
208
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com'
209
+ # req.raw_host_with_port # => "example.com"
208
210
  #
209
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
210
- # req.raw_host_with_port # => "example.com:80"
211
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
212
+ # req.raw_host_with_port # => "example.com:80"
211
213
  #
212
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
213
- # req.raw_host_with_port # => "example.com:8080"
214
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
215
+ # req.raw_host_with_port # => "example.com:8080"
214
216
  def raw_host_with_port
215
217
  if forwarded = x_forwarded_host.presence
216
218
  forwarded.split(/,\s?/).last
@@ -221,35 +223,35 @@ module ActionDispatch
221
223
 
222
224
  # Returns the host for this request, such as "example.com".
223
225
  #
224
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
225
- # req.host # => "example.com"
226
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
227
+ # req.host # => "example.com"
226
228
  def host
227
229
  raw_host_with_port.sub(/:\d+$/, "")
228
230
  end
229
231
 
230
- # Returns a \host:\port string for this request, such as "example.com" or
231
- # "example.com:8080". Port is only included if it is not a default port
232
- # (80 or 443)
232
+ # Returns a host:port string for this request, such as "example.com" or
233
+ # "example.com:8080". Port is only included if it is not a default port (80 or
234
+ # 443)
233
235
  #
234
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com'
235
- # req.host_with_port # => "example.com"
236
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com'
237
+ # req.host_with_port # => "example.com"
236
238
  #
237
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
238
- # req.host_with_port # => "example.com"
239
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
240
+ # req.host_with_port # => "example.com"
239
241
  #
240
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
241
- # req.host_with_port # => "example.com:8080"
242
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
243
+ # req.host_with_port # => "example.com:8080"
242
244
  def host_with_port
243
245
  "#{host}#{port_string}"
244
246
  end
245
247
 
246
248
  # Returns the port number of this request as an integer.
247
249
  #
248
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com'
249
- # req.port # => 80
250
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com'
251
+ # req.port # => 80
250
252
  #
251
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
252
- # req.port # => 8080
253
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
254
+ # req.port # => 8080
253
255
  def port
254
256
  @port ||= if raw_host_with_port =~ /:(\d+)$/
255
257
  $1.to_i
@@ -258,10 +260,10 @@ module ActionDispatch
258
260
  end
259
261
  end
260
262
 
261
- # Returns the standard \port number for this request's protocol.
263
+ # Returns the standard port number for this request's protocol.
262
264
  #
263
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
264
- # req.standard_port # => 80
265
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
266
+ # req.standard_port # => 80
265
267
  def standard_port
266
268
  if "https://" == protocol
267
269
  443
@@ -272,68 +274,68 @@ module ActionDispatch
272
274
 
273
275
  # Returns whether this request is using the standard port
274
276
  #
275
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
276
- # req.standard_port? # => true
277
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
278
+ # req.standard_port? # => true
277
279
  #
278
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
279
- # req.standard_port? # => false
280
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
281
+ # req.standard_port? # => false
280
282
  def standard_port?
281
283
  port == standard_port
282
284
  end
283
285
 
284
- # Returns a number \port suffix like 8080 if the \port number of this request
285
- # is not the default HTTP \port 80 or HTTPS \port 443.
286
+ # Returns a number port suffix like 8080 if the port number of this request is
287
+ # not the default HTTP port 80 or HTTPS port 443.
286
288
  #
287
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
288
- # req.optional_port # => nil
289
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
290
+ # req.optional_port # => nil
289
291
  #
290
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
291
- # req.optional_port # => 8080
292
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
293
+ # req.optional_port # => 8080
292
294
  def optional_port
293
295
  standard_port? ? nil : port
294
296
  end
295
297
 
296
- # Returns a string \port suffix, including colon, like ":8080" if the \port
297
- # number of this request is not the default HTTP \port 80 or HTTPS \port 443.
298
+ # Returns a string port suffix, including colon, like ":8080" if the port number
299
+ # of this request is not the default HTTP port 80 or HTTPS port 443.
298
300
  #
299
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
300
- # req.port_string # => ""
301
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
302
+ # req.port_string # => ""
301
303
  #
302
- # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
303
- # req.port_string # => ":8080"
304
+ # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
305
+ # req.port_string # => ":8080"
304
306
  def port_string
305
307
  standard_port? ? "" : ":#{port}"
306
308
  end
307
309
 
308
310
  # Returns the requested port, such as 8080, based on SERVER_PORT
309
311
  #
310
- # req = ActionDispatch::Request.new 'SERVER_PORT' => '80'
311
- # req.server_port # => 80
312
+ # req = ActionDispatch::Request.new 'SERVER_PORT' => '80'
313
+ # req.server_port # => 80
312
314
  #
313
- # req = ActionDispatch::Request.new 'SERVER_PORT' => '8080'
314
- # req.server_port # => 8080
315
+ # req = ActionDispatch::Request.new 'SERVER_PORT' => '8080'
316
+ # req.server_port # => 8080
315
317
  def server_port
316
318
  get_header("SERVER_PORT").to_i
317
319
  end
318
320
 
319
- # Returns the \domain part of a \host, such as "rubyonrails.org" in "www.rubyonrails.org". You can specify
320
- # a different <tt>tld_length</tt>, such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk".
321
+ # Returns the domain part of a host, such as "rubyonrails.org" in
322
+ # "www.rubyonrails.org". You can specify a different `tld_length`, such as 2 to
323
+ # catch rubyonrails.co.uk in "www.rubyonrails.co.uk".
321
324
  def domain(tld_length = @@tld_length)
322
325
  ActionDispatch::Http::URL.extract_domain(host, tld_length)
323
326
  end
324
327
 
325
- # Returns all the \subdomains as an array, so <tt>["dev", "www"]</tt> would be
326
- # returned for "dev.www.rubyonrails.org". You can specify a different <tt>tld_length</tt>,
327
- # such as 2 to catch <tt>["www"]</tt> instead of <tt>["www", "rubyonrails"]</tt>
328
- # in "www.rubyonrails.co.uk".
328
+ # Returns all the subdomains as an array, so `["dev", "www"]` would be returned
329
+ # for "dev.www.rubyonrails.org". You can specify a different `tld_length`, such
330
+ # as 2 to catch `["www"]` instead of `["www", "rubyonrails"]` in
331
+ # "www.rubyonrails.co.uk".
329
332
  def subdomains(tld_length = @@tld_length)
330
333
  ActionDispatch::Http::URL.extract_subdomains(host, tld_length)
331
334
  end
332
335
 
333
- # Returns all the \subdomains as a string, so <tt>"dev.www"</tt> would be
334
- # returned for "dev.www.rubyonrails.org". You can specify a different <tt>tld_length</tt>,
335
- # such as 2 to catch <tt>"www"</tt> instead of <tt>"www.rubyonrails"</tt>
336
- # in "www.rubyonrails.co.uk".
336
+ # Returns all the subdomains as a string, so `"dev.www"` would be returned for
337
+ # "dev.www.rubyonrails.org". You can specify a different `tld_length`, such as 2
338
+ # to catch `"www"` instead of `"www.rubyonrails"` in "www.rubyonrails.co.uk".
337
339
  def subdomain(tld_length = @@tld_length)
338
340
  ActionDispatch::Http::URL.extract_subdomain(host, tld_length)
339
341
  end
@@ -1,12 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "action_controller/metal/exceptions"
4
6
 
5
7
  module ActionDispatch
6
8
  # :stopdoc:
7
9
  module Journey
8
10
  # The Formatter class is used for formatting URLs. For example, parameters
9
- # passed to +url_for+ in Rails will eventually call Formatter#generate.
11
+ # passed to `url_for` in Rails will eventually call Formatter#generate.
10
12
  class Formatter
11
13
  attr_reader :routes
12
14
 
@@ -57,21 +59,27 @@ module ActionDispatch
57
59
  end
58
60
 
59
61
  def generate(name, options, path_parameters)
62
+ original_options = options.dup
63
+ path_params = options.delete(:path_params) || {}
64
+ options = path_params.merge(options)
60
65
  constraints = path_parameters.merge(options)
61
66
  missing_keys = nil
62
67
 
63
68
  match_route(name, constraints) do |route|
64
69
  parameterized_parts = extract_parameterized_parts(route, options, path_parameters)
65
70
 
66
- # Skip this route unless a name has been provided or it is a
67
- # standard Rails route since we can't determine whether an options
68
- # hash passed to url_for matches a Rack application or a redirect.
71
+ # Skip this route unless a name has been provided or it is a standard Rails
72
+ # route since we can't determine whether an options hash passed to url_for
73
+ # matches a Rack application or a redirect.
69
74
  next unless name || route.dispatcher?
70
75
 
71
76
  missing_keys = missing_keys(route, parameterized_parts)
72
77
  next if missing_keys && !missing_keys.empty?
73
- params = options.dup.delete_if do |key, _|
74
- parameterized_parts.key?(key) || route.defaults.key?(key)
78
+ params = options.delete_if do |key, _|
79
+ # top-level params' normal behavior of generating query_params should be
80
+ # preserved even if the same key is also a bind_param
81
+ parameterized_parts.key?(key) || route.defaults.key?(key) ||
82
+ (path_params.key?(key) && !original_options.key?(key))
75
83
  end
76
84
 
77
85
  defaults = route.defaults
@@ -98,6 +106,11 @@ module ActionDispatch
98
106
  @cache = nil
99
107
  end
100
108
 
109
+ def eager_load!
110
+ cache
111
+ nil
112
+ end
113
+
101
114
  private
102
115
  def extract_parameterized_parts(route, options, recall)
103
116
  parameterized_parts = recall.merge(options)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "action_dispatch/journey/gtg/transition_table"
4
6
 
5
7
  module ActionDispatch
@@ -66,9 +68,8 @@ module ActionDispatch
66
68
  when Nodes::Group
67
69
  true
68
70
  when Nodes::Star
69
- # the default star regex is /(.+)/ which is NOT nullable
70
- # but since different constraints can be provided we must
71
- # actually check if this is the case or not.
71
+ # the default star regex is /(.+)/ which is NOT nullable but since different
72
+ # constraints can be provided we must actually check if this is the case or not.
72
73
  node.regexp.match?("")
73
74
  when Nodes::Or
74
75
  node.children.any? { |c| nullable?(c) }
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "strscan"
4
6
 
5
7
  module ActionDispatch
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "action_dispatch/journey/nfa/dot"
4
6
 
5
7
  module ActionDispatch
@@ -55,8 +57,8 @@ module ActionDispatch
55
57
 
56
58
  t.each { |s, previous_start|
57
59
  if previous_start.nil?
58
- # In the simple case of a "default" param regex do this fast-path
59
- # and add all next states.
60
+ # In the simple case of a "default" param regex do this fast-path and add all
61
+ # next states.
60
62
  if token_matches_default_component && states = @stdparam_states[s]
61
63
  states.each { |re, v| next_states << [v, nil].freeze if !v.nil? }
62
64
  end
@@ -67,10 +69,10 @@ module ActionDispatch
67
69
  end
68
70
  end
69
71
 
70
- # For regexes that aren't the "default" style, they may potentially
71
- # not be terminated by the first "token" [./?], so we need to continue
72
- # to attempt to match this regexp as well as any successful paths that
73
- # continue out of it. both paths could be valid.
72
+ # For regexes that aren't the "default" style, they may potentially not be
73
+ # terminated by the first "token" [./?], so we need to continue to attempt to
74
+ # match this regexp as well as any successful paths that continue out of it.
75
+ # both paths could be valid.
74
76
  if states = @regexp_states[s]
75
77
  slice_start = if previous_start.nil?
76
78
  start_index
@@ -86,8 +88,8 @@ module ActionDispatch
86
88
  next_states << [v, nil].freeze if !v.nil? && re.match?(curr_slice)
87
89
  }
88
90
 
89
- # and regardless, we must continue accepting tokens and retrying this regexp.
90
- # we need to remember where we started as well so we can take bigger slices.
91
+ # and regardless, we must continue accepting tokens and retrying this regexp. we
92
+ # need to remember where we started as well so we can take bigger slices.
91
93
  next_states << [s, slice_start].freeze
92
94
  end
93
95
  }
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionDispatch
4
6
  module Journey # :nodoc:
5
7
  module NFA # :nodoc:
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "action_dispatch/journey/visitors"
4
6
 
5
7
  module ActionDispatch
@@ -21,9 +23,8 @@ module ActionDispatch
21
23
  end
22
24
 
23
25
  def requirements=(requirements)
24
- # inject any regexp requirements for `star` nodes so they can be
25
- # determined nullable, which requires knowing if the regex accepts an
26
- # empty string.
26
+ # inject any regexp requirements for `star` nodes so they can be determined
27
+ # nullable, which requires knowing if the regex accepts an empty string.
27
28
  (symbols + stars).each do |node|
28
29
  re = requirements[node.to_sym]
29
30
  node.regexp = re if re
@@ -51,8 +52,8 @@ module ActionDispatch
51
52
  stars << node
52
53
 
53
54
  if formatted != false
54
- # Add a constraint for wildcard route to make it non-greedy and
55
- # match the optional format part of the route by default.
55
+ # Add a constraint for wildcard route to make it non-greedy and match the
56
+ # optional format part of the route by default.
56
57
  wildcard_options[node.name.to_sym] ||= /.+?/m
57
58
  end
58
59
  end
@@ -1,8 +1,9 @@
1
1
  #
2
2
  # DO NOT MODIFY!!!!
3
- # This file is automatically generated by Racc 1.4.16
4
- # from Racc grammar file "".
5
- #
3
+ # This file is automatically generated by Racc 1.4.16 from
4
+ # Racc grammar file "".
5
+
6
+ # :markup: markdown
6
7
 
7
8
  require 'racc/parser.rb'
8
9
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "action_dispatch/journey/scanner"
4
6
  require "action_dispatch/journey/nodes/node"
5
7
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionDispatch
4
6
  module Journey # :nodoc:
5
7
  module Path # :nodoc:
@@ -32,7 +34,8 @@ module ActionDispatch
32
34
  end
33
35
 
34
36
  def requirements_anchored?
35
- # each required param must not be surrounded by a literal, otherwise it isn't simple to chunk-match the url piecemeal
37
+ # each required param must not be surrounded by a literal, otherwise it isn't
38
+ # simple to chunk-match the url piecemeal
36
39
  terminals = ast.terminals
37
40
 
38
41
  terminals.each_with_index { |s, index|
@@ -183,22 +186,22 @@ module ActionDispatch
183
186
  end
184
187
 
185
188
  def offsets
186
- return @offsets if @offsets
187
-
188
- @offsets = [0]
189
-
190
- spec.find_all(&:symbol?).each do |node|
191
- node = node.to_sym
192
-
193
- if @requirements.key?(node)
194
- re = /#{Regexp.union(@requirements[node])}|/
195
- @offsets.push((re.match("").length - 1) + @offsets.last)
196
- else
197
- @offsets << @offsets.last
189
+ @offsets ||= begin
190
+ offsets = [0]
191
+
192
+ spec.find_all(&:symbol?).each do |node|
193
+ node = node.to_sym
194
+
195
+ if @requirements.key?(node)
196
+ re = /#{Regexp.union(@requirements[node])}|/
197
+ offsets.push((re.match("").length - 1) + offsets.last)
198
+ else
199
+ offsets << offsets.last
200
+ end
198
201
  end
199
- end
200
202
 
201
- @offsets
203
+ offsets
204
+ end
202
205
  end
203
206
  end
204
207
  end
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionDispatch
4
6
  # :stopdoc:
5
7
  module Journey
6
8
  class Route
7
9
  attr_reader :app, :path, :defaults, :name, :precedence, :constraints,
8
- :internal, :scope_options, :ast
10
+ :internal, :scope_options, :ast, :source_location
9
11
 
10
12
  alias :conditions :constraints
11
13
 
@@ -52,8 +54,8 @@ module ActionDispatch
52
54
 
53
55
  ##
54
56
  # +path+ is a path constraint.
55
- # +constraints+ is a hash of constraints to be applied to this route.
56
- def initialize(name:, app: nil, path:, constraints: {}, required_defaults: [], defaults: {}, request_method_match: nil, precedence: 0, scope_options: {}, internal: false)
57
+ # `constraints` is a hash of constraints to be applied to this route.
58
+ def initialize(name:, app: nil, path:, constraints: {}, required_defaults: [], defaults: {}, request_method_match: nil, precedence: 0, scope_options: {}, internal: false, source_location: nil)
57
59
  @name = name
58
60
  @app = app
59
61
  @path = path
@@ -69,6 +71,7 @@ module ActionDispatch
69
71
  @path_formatter = @path.build_formatter
70
72
  @scope_options = scope_options
71
73
  @internal = internal
74
+ @source_location = source_location
72
75
 
73
76
  @ast = @path.ast.root
74
77
  @path.ast.route = self
@@ -81,14 +84,14 @@ module ActionDispatch
81
84
  nil
82
85
  end
83
86
 
84
- # Needed for `bin/rails routes`. Picks up succinctly defined requirements
85
- # for a route, for example route
87
+ # Needed for `bin/rails routes`. Picks up succinctly defined requirements for a
88
+ # route, for example route
86
89
  #
87
- # get 'photo/:id', :controller => 'photos', :action => 'show',
88
- # :id => /[A-Z]\d{5}/
90
+ # get 'photo/:id', :controller => 'photos', :action => 'show',
91
+ # :id => /[A-Z]\d{5}/
89
92
  #
90
- # will have {:controller=>"photos", :action=>"show", :id=>/[A-Z]\d{5}/}
91
- # as requirements.
93
+ # will have {:controller=>"photos", :action=>"show", :[id=>/](A-Z){5}/} as
94
+ # requirements.
92
95
  def requirements
93
96
  @defaults.merge(path.requirements).delete_if { |_, v|
94
97
  /.+?/m == v
@@ -1,19 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionDispatch
4
6
  module Journey # :nodoc:
5
7
  class Router # :nodoc:
6
8
  class Utils # :nodoc:
7
9
  # Normalizes URI path.
8
10
  #
9
- # Strips off trailing slash and ensures there is a leading slash.
10
- # Also converts downcase URL encoded string to uppercase.
11
+ # Strips off trailing slash and ensures there is a leading slash. Also converts
12
+ # downcase URL encoded string to uppercase.
11
13
  #
12
- # normalize_path("/foo") # => "/foo"
13
- # normalize_path("/foo/") # => "/foo"
14
- # normalize_path("foo") # => "/foo"
15
- # normalize_path("") # => "/"
16
- # normalize_path("/%ab") # => "/%AB"
14
+ # normalize_path("/foo") # => "/foo"
15
+ # normalize_path("/foo/") # => "/foo"
16
+ # normalize_path("foo") # => "/foo"
17
+ # normalize_path("") # => "/"
18
+ # normalize_path("/%ab") # => "/%AB"
17
19
  def self.normalize_path(path)
18
20
  path ||= ""
19
21
  encoding = path.encoding
@@ -28,8 +30,7 @@ module ActionDispatch
28
30
  path.force_encoding(encoding)
29
31
  end
30
32
 
31
- # URI path and fragment escaping
32
- # https://tools.ietf.org/html/rfc3986
33
+ # URI path and fragment escaping https://tools.ietf.org/html/rfc3986
33
34
  class UriEncoder # :nodoc:
34
35
  ENCODE = "%%%02X"
35
36
  US_ASCII = Encoding::US_ASCII
@@ -42,11 +43,11 @@ module ActionDispatch
42
43
  UNRESERVED = "#{ALPHA}#{DIGIT}\\-\\._~"
43
44
  SUB_DELIMS = "!\\$&'\\(\\)\\*\\+,;="
44
45
 
45
- ESCAPED = /%[a-zA-Z0-9]{2}/.freeze
46
+ ESCAPED = /%[a-zA-Z0-9]{2}/
46
47
 
47
- FRAGMENT = /[^#{UNRESERVED}#{SUB_DELIMS}:@\/?]/.freeze
48
- SEGMENT = /[^#{UNRESERVED}#{SUB_DELIMS}:@]/.freeze
49
- PATH = /[^#{UNRESERVED}#{SUB_DELIMS}:@\/]/.freeze
48
+ FRAGMENT = /[^#{UNRESERVED}#{SUB_DELIMS}:@\/?]/
49
+ SEGMENT = /[^#{UNRESERVED}#{SUB_DELIMS}:@]/
50
+ PATH = /[^#{UNRESERVED}#{SUB_DELIMS}:@\/]/
50
51
 
51
52
  def escape_fragment(fragment)
52
53
  escape(fragment, FRAGMENT)
@@ -93,8 +94,8 @@ module ActionDispatch
93
94
 
94
95
  # Replaces any escaped sequences with their unescaped representations.
95
96
  #
96
- # uri = "/topics?title=Ruby%20on%20Rails"
97
- # unescape_uri(uri) #=> "/topics?title=Ruby on Rails"
97
+ # uri = "/topics?title=Ruby%20on%20Rails"
98
+ # unescape_uri(uri) #=> "/topics?title=Ruby on Rails"
98
99
  def self.unescape_uri(uri)
99
100
  ENCODER.unescape_uri(uri)
100
101
  end