actionpack 5.2.8.1 → 6.0.6

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 (136) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +270 -347
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -3
  5. data/lib/abstract_controller/base.rb +4 -3
  6. data/lib/abstract_controller/caching/fragments.rb +6 -22
  7. data/lib/abstract_controller/caching.rb +1 -1
  8. data/lib/abstract_controller/callbacks.rb +12 -0
  9. data/lib/abstract_controller/collector.rb +1 -2
  10. data/lib/abstract_controller/helpers.rb +7 -6
  11. data/lib/abstract_controller/railties/routes_helpers.rb +1 -1
  12. data/lib/abstract_controller/translation.rb +4 -4
  13. data/lib/action_controller/api.rb +2 -1
  14. data/lib/action_controller/base.rb +2 -7
  15. data/lib/action_controller/caching.rb +1 -2
  16. data/lib/action_controller/log_subscriber.rb +8 -5
  17. data/lib/action_controller/metal/basic_implicit_render.rb +1 -1
  18. data/lib/action_controller/metal/conditional_get.rb +9 -3
  19. data/lib/action_controller/metal/content_security_policy.rb +0 -1
  20. data/lib/action_controller/metal/data_streaming.rb +5 -6
  21. data/lib/action_controller/metal/default_headers.rb +17 -0
  22. data/lib/action_controller/metal/etag_with_template_digest.rb +1 -1
  23. data/lib/action_controller/metal/exceptions.rb +23 -2
  24. data/lib/action_controller/metal/flash.rb +5 -5
  25. data/lib/action_controller/metal/force_ssl.rb +15 -56
  26. data/lib/action_controller/metal/head.rb +1 -1
  27. data/lib/action_controller/metal/helpers.rb +3 -4
  28. data/lib/action_controller/metal/http_authentication.rb +20 -21
  29. data/lib/action_controller/metal/implicit_render.rb +4 -14
  30. data/lib/action_controller/metal/instrumentation.rb +3 -6
  31. data/lib/action_controller/metal/live.rb +29 -31
  32. data/lib/action_controller/metal/mime_responds.rb +13 -2
  33. data/lib/action_controller/metal/params_wrapper.rb +18 -14
  34. data/lib/action_controller/metal/redirecting.rb +5 -5
  35. data/lib/action_controller/metal/renderers.rb +4 -4
  36. data/lib/action_controller/metal/rendering.rb +2 -3
  37. data/lib/action_controller/metal/request_forgery_protection.rb +25 -48
  38. data/lib/action_controller/metal/streaming.rb +0 -1
  39. data/lib/action_controller/metal/strong_parameters.rb +65 -44
  40. data/lib/action_controller/metal/url_for.rb +1 -1
  41. data/lib/action_controller/metal.rb +8 -6
  42. data/lib/action_controller/railties/helpers.rb +1 -1
  43. data/lib/action_controller/renderer.rb +17 -3
  44. data/lib/action_controller/template_assertions.rb +1 -1
  45. data/lib/action_controller/test_case.rb +7 -8
  46. data/lib/action_controller.rb +5 -1
  47. data/lib/action_dispatch/http/cache.rb +14 -11
  48. data/lib/action_dispatch/http/content_disposition.rb +45 -0
  49. data/lib/action_dispatch/http/content_security_policy.rb +28 -17
  50. data/lib/action_dispatch/http/filter_parameters.rb +8 -7
  51. data/lib/action_dispatch/http/filter_redirect.rb +1 -2
  52. data/lib/action_dispatch/http/headers.rb +1 -2
  53. data/lib/action_dispatch/http/mime_negotiation.rb +13 -6
  54. data/lib/action_dispatch/http/mime_type.rb +14 -8
  55. data/lib/action_dispatch/http/parameter_filter.rb +5 -79
  56. data/lib/action_dispatch/http/parameters.rb +15 -6
  57. data/lib/action_dispatch/http/request.rb +21 -14
  58. data/lib/action_dispatch/http/response.rb +40 -21
  59. data/lib/action_dispatch/http/upload.rb +9 -1
  60. data/lib/action_dispatch/http/url.rb +81 -82
  61. data/lib/action_dispatch/journey/formatter.rb +2 -3
  62. data/lib/action_dispatch/journey/gtg/builder.rb +0 -1
  63. data/lib/action_dispatch/journey/gtg/transition_table.rb +0 -1
  64. data/lib/action_dispatch/journey/nfa/simulator.rb +0 -2
  65. data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -1
  66. data/lib/action_dispatch/journey/nodes/node.rb +9 -8
  67. data/lib/action_dispatch/journey/path/pattern.rb +6 -3
  68. data/lib/action_dispatch/journey/route.rb +5 -4
  69. data/lib/action_dispatch/journey/router/utils.rb +10 -10
  70. data/lib/action_dispatch/journey/router.rb +0 -4
  71. data/lib/action_dispatch/journey/routes.rb +0 -2
  72. data/lib/action_dispatch/journey/scanner.rb +10 -4
  73. data/lib/action_dispatch/journey/visitors.rb +1 -4
  74. data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
  75. data/lib/action_dispatch/middleware/callbacks.rb +2 -4
  76. data/lib/action_dispatch/middleware/cookies.rb +62 -78
  77. data/lib/action_dispatch/middleware/debug_exceptions.rb +45 -61
  78. data/lib/action_dispatch/middleware/debug_locks.rb +5 -5
  79. data/lib/action_dispatch/middleware/debug_view.rb +66 -0
  80. data/lib/action_dispatch/middleware/exception_wrapper.rb +49 -16
  81. data/lib/action_dispatch/middleware/flash.rb +1 -1
  82. data/lib/action_dispatch/middleware/host_authorization.rb +121 -0
  83. data/lib/action_dispatch/middleware/public_exceptions.rb +6 -3
  84. data/lib/action_dispatch/middleware/remote_ip.rb +9 -12
  85. data/lib/action_dispatch/middleware/request_id.rb +2 -2
  86. data/lib/action_dispatch/middleware/session/abstract_store.rb +0 -1
  87. data/lib/action_dispatch/middleware/session/cookie_store.rb +1 -7
  88. data/lib/action_dispatch/middleware/show_exceptions.rb +1 -2
  89. data/lib/action_dispatch/middleware/ssl.rb +8 -8
  90. data/lib/action_dispatch/middleware/stack.rb +38 -2
  91. data/lib/action_dispatch/middleware/static.rb +6 -7
  92. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  93. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  94. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +3 -1
  95. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  96. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +4 -2
  97. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +45 -35
  98. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
  99. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
  100. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -4
  101. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
  102. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +7 -4
  103. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +5 -2
  104. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +4 -0
  105. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
  106. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  107. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +2 -2
  108. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -1
  109. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +2 -2
  110. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +3 -0
  111. data/lib/action_dispatch/railtie.rb +7 -2
  112. data/lib/action_dispatch/request/session.rb +9 -2
  113. data/lib/action_dispatch/routing/inspector.rb +97 -50
  114. data/lib/action_dispatch/routing/mapper.rb +63 -42
  115. data/lib/action_dispatch/routing/polymorphic_routes.rb +3 -6
  116. data/lib/action_dispatch/routing/route_set.rb +25 -31
  117. data/lib/action_dispatch/routing/url_for.rb +2 -2
  118. data/lib/action_dispatch/routing.rb +21 -20
  119. data/lib/action_dispatch/system_test_case.rb +44 -6
  120. data/lib/action_dispatch/system_testing/browser.rb +38 -7
  121. data/lib/action_dispatch/system_testing/driver.rb +11 -2
  122. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +6 -5
  123. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +7 -6
  124. data/lib/action_dispatch/testing/assertion_response.rb +0 -1
  125. data/lib/action_dispatch/testing/assertions/response.rb +2 -3
  126. data/lib/action_dispatch/testing/assertions/routing.rb +15 -3
  127. data/lib/action_dispatch/testing/assertions.rb +1 -1
  128. data/lib/action_dispatch/testing/integration.rb +33 -12
  129. data/lib/action_dispatch/testing/request_encoder.rb +2 -2
  130. data/lib/action_dispatch/testing/test_process.rb +2 -2
  131. data/lib/action_dispatch/testing/test_response.rb +4 -32
  132. data/lib/action_dispatch.rb +7 -2
  133. data/lib/action_pack/gem_version.rb +4 -4
  134. data/lib/action_pack.rb +1 -1
  135. metadata +29 -15
  136. data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +0 -26
@@ -10,12 +10,15 @@
10
10
  <div id="container">
11
11
  <h2>
12
12
  <%= h @exception.message %>
13
- <% if %r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}.match?(@exception.message) %>
14
- <br />To resolve this issue run: bin/rails active_storage:install
13
+ <% if defined?(ActiveStorage) && @exception.message.match?(%r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}) %>
14
+ <br />To resolve this issue run: rails active_storage:install
15
+ <% end %>
16
+ <% if defined?(ActionMailbox) && @exception.message.match?(%r{#{ActionMailbox::InboundEmail.table_name}}) %>
17
+ <br />To resolve this issue run: rails action_mailbox:install
15
18
  <% end %>
16
19
  </h2>
17
20
 
18
- <%= render template: "rescues/_source" %>
19
- <%= render template: "rescues/_trace" %>
21
+ <%= render "rescues/source", source_extracts: @source_extracts, show_source_idx: @show_source_idx %>
22
+ <%= render "rescues/trace", traces: @traces, trace_to_show: @trace_to_show %>
20
23
  <%= render template: "rescues/_request_and_response" %>
21
24
  </div>
@@ -4,8 +4,11 @@
4
4
  <% end %>
5
5
 
6
6
  <%= @exception.message %>
7
- <% if %r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}.match?(@exception.message) %>
8
- To resolve this issue run: bin/rails active_storage:install
7
+ <% if defined?(ActiveStorage) && @exception.message.match?(%r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}) %>
8
+ To resolve this issue run: rails active_storage:install
9
+ <% end %>
10
+ <% if defined?(ActionMailbox) && @exception.message.match?(%r{#{ActionMailbox::InboundEmail.table_name}}) %>
11
+ To resolve this issue run: rails action_mailbox:install
9
12
  <% end %>
10
13
 
11
14
  <%= render template: "rescues/_source" %>
@@ -117,6 +117,10 @@
117
117
  background-color: #FFCCCC;
118
118
  }
119
119
 
120
+ .button_to {
121
+ display: inline-block;
122
+ }
123
+
120
124
  .hidden {
121
125
  display: none;
122
126
  }
@@ -0,0 +1,19 @@
1
+ <header>
2
+ <h1>No template for interactive request</h1>
3
+ </header>
4
+
5
+ <div id="container">
6
+ <h2><%= h @exception.message %></h2>
7
+
8
+ <p class="summary">
9
+ <strong>NOTE!</strong><br>
10
+ Unless told otherwise, Rails expects an action to render a template with the same name,<br>
11
+ contained in a folder named after its controller.
12
+
13
+ If this controller is an API responding with 204 (No Content), <br>
14
+ which does not require a template,
15
+ then this error will occur when trying to access it via browser,<br>
16
+ since we expect an HTML template
17
+ to be rendered for such requests. If that's the case, carry on.
18
+ </p>
19
+ </div>
@@ -0,0 +1,3 @@
1
+ Missing exact template
2
+
3
+ <%= @exception.message %>
@@ -5,7 +5,7 @@
5
5
  <div id="container">
6
6
  <h2><%= h @exception.message %></h2>
7
7
 
8
- <%= render template: "rescues/_source" %>
9
- <%= render template: "rescues/_trace" %>
8
+ <%= render "rescues/source", source_extracts: @source_extracts, show_source_idx: @show_source_idx %>
9
+ <%= render "rescues/trace", traces: @traces, trace_to_show: @trace_to_show %>
10
10
  <%= render template: "rescues/_request_and_response" %>
11
11
  </div>
@@ -14,7 +14,7 @@
14
14
  </p>
15
15
  <% end %>
16
16
 
17
- <%= render template: "rescues/_trace" %>
17
+ <%= render "rescues/trace", traces: @traces, trace_to_show: @trace_to_show %>
18
18
 
19
19
  <% if @routes_inspector %>
20
20
  <h2>
@@ -11,10 +11,10 @@
11
11
  </p>
12
12
  <pre><code><%= h @exception.message %></code></pre>
13
13
 
14
- <%= render template: "rescues/_source" %>
14
+ <%= render "rescues/source", source_extracts: @source_extracts, show_source_idx: @show_source_idx %>
15
15
 
16
16
  <p><%= @exception.sub_template_message %></p>
17
17
 
18
- <%= render template: "rescues/_trace" %>
18
+ <%= render "rescues/trace", traces: @traces, trace_to_show: @trace_to_show %>
19
19
  <%= render template: "rescues/_request_and_response" %>
20
20
  </div>
@@ -197,4 +197,7 @@
197
197
 
198
198
  setupMatchPaths();
199
199
  setupRouteToggleHelperLinks();
200
+
201
+ // Focus the search input after page has loaded
202
+ document.getElementById('search').focus();
200
203
  </script>
@@ -21,7 +21,9 @@ module ActionDispatch
21
21
  config.action_dispatch.encrypted_signed_cookie_salt = "signed encrypted cookie"
22
22
  config.action_dispatch.authenticated_encrypted_cookie_salt = "authenticated encrypted cookie"
23
23
  config.action_dispatch.use_authenticated_cookie_encryption = false
24
+ config.action_dispatch.use_cookies_with_metadata = false
24
25
  config.action_dispatch.perform_deep_munge = true
26
+ config.action_dispatch.return_only_media_type_on_content_type = true
25
27
 
26
28
  config.action_dispatch.default_headers = {
27
29
  "X-Frame-Options" => "SAMEORIGIN",
@@ -40,8 +42,11 @@ module ActionDispatch
40
42
  ActionDispatch::Http::URL.tld_length = app.config.action_dispatch.tld_length
41
43
  ActionDispatch::Request.ignore_accept_header = app.config.action_dispatch.ignore_accept_header
42
44
  ActionDispatch::Request::Utils.perform_deep_munge = app.config.action_dispatch.perform_deep_munge
43
- ActionDispatch::Response.default_charset = app.config.action_dispatch.default_charset || app.config.encoding
44
- ActionDispatch::Response.default_headers = app.config.action_dispatch.default_headers
45
+ ActiveSupport.on_load(:action_dispatch_response) do
46
+ self.default_charset = app.config.action_dispatch.default_charset || app.config.encoding
47
+ self.default_headers = app.config.action_dispatch.default_headers
48
+ self.return_only_media_type_on_content_type = app.config.action_dispatch.return_only_media_type_on_content_type
49
+ end
45
50
 
46
51
  ActionDispatch::ExceptionWrapper.rescue_responses.merge!(config.action_dispatch.rescue_responses)
47
52
  ActionDispatch::ExceptionWrapper.rescue_templates.merge!(config.action_dispatch.rescue_templates)
@@ -93,12 +93,20 @@ module ActionDispatch
93
93
  key = key.to_s
94
94
 
95
95
  if key == "session_id"
96
- id && id.public_id
96
+ id&.public_id
97
97
  else
98
98
  @delegate[key]
99
99
  end
100
100
  end
101
101
 
102
+ # Returns the nested value specified by the sequence of keys, returning
103
+ # +nil+ if any intermediate step is +nil+.
104
+ def dig(*keys)
105
+ load_for_read!
106
+ keys = keys.map.with_index { |key, i| i.zero? ? key.to_s : key }
107
+ @delegate.dig(*keys)
108
+ end
109
+
102
110
  # Returns true if the session has the given key or false.
103
111
  def has_key?(key)
104
112
  load_for_read!
@@ -214,7 +222,6 @@ module ActionDispatch
214
222
  end
215
223
 
216
224
  private
217
-
218
225
  def load_for_read!
219
226
  load! if !loaded? && exists?
220
227
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "delegate"
4
- require "active_support/core_ext/string/strip"
4
+ require "io/console/size"
5
5
 
6
6
  module ActionDispatch
7
7
  module Routing
@@ -61,11 +61,11 @@ module ActionDispatch
61
61
  @routes = routes
62
62
  end
63
63
 
64
- def format(formatter, filter = nil)
64
+ def format(formatter, filter = {})
65
65
  routes_to_display = filter_routes(normalize_filter(filter))
66
66
  routes = collect_routes(routes_to_display)
67
67
  if routes.none?
68
- formatter.no_routes(collect_routes(@routes))
68
+ formatter.no_routes(collect_routes(@routes), filter)
69
69
  return formatter.result
70
70
  end
71
71
 
@@ -81,12 +81,12 @@ module ActionDispatch
81
81
  end
82
82
 
83
83
  private
84
-
85
84
  def normalize_filter(filter)
86
- if filter.is_a?(Hash) && filter[:controller]
85
+ if filter[:controller]
87
86
  { controller: /#{filter[:controller].underscore.sub(/_?controller\z/, "")}/ }
88
- elsif filter
89
- { controller: /#{filter}/, action: /#{filter}/, verb: /#{filter}/, name: /#{filter}/, path: /#{filter}/ }
87
+ elsif filter[:grep]
88
+ { controller: /#{filter[:grep]}/, action: /#{filter[:grep]}/,
89
+ verb: /#{filter[:grep]}/, name: /#{filter[:grep]}/, path: /#{filter[:grep]}/ }
90
90
  end
91
91
  end
92
92
 
@@ -126,62 +126,109 @@ module ActionDispatch
126
126
  end
127
127
  end
128
128
 
129
- class ConsoleFormatter
130
- def initialize
131
- @buffer = []
132
- end
129
+ module ConsoleFormatter
130
+ class Base
131
+ def initialize
132
+ @buffer = []
133
+ end
133
134
 
134
- def result
135
- @buffer.join("\n")
136
- end
135
+ def result
136
+ @buffer.join("\n")
137
+ end
137
138
 
138
- def section_title(title)
139
- @buffer << "\n#{title}:"
140
- end
139
+ def section_title(title)
140
+ end
141
141
 
142
- def section(routes)
143
- @buffer << draw_section(routes)
144
- end
142
+ def section(routes)
143
+ end
145
144
 
146
- def header(routes)
147
- @buffer << draw_header(routes)
148
- end
145
+ def header(routes)
146
+ end
149
147
 
150
- def no_routes(routes)
151
- @buffer <<
152
- if routes.none?
153
- <<-MESSAGE.strip_heredoc
154
- You don't have any routes defined!
148
+ def no_routes(routes, filter)
149
+ @buffer <<
150
+ if routes.none?
151
+ <<~MESSAGE
152
+ You don't have any routes defined!
153
+
154
+ Please add some routes in config/routes.rb.
155
+ MESSAGE
156
+ elsif filter.key?(:controller)
157
+ "No routes were found for this controller."
158
+ elsif filter.key?(:grep)
159
+ "No routes were found for this grep pattern."
160
+ end
155
161
 
156
- Please add some routes in config/routes.rb.
157
- MESSAGE
158
- else
159
- "No routes were found for this controller"
162
+ @buffer << "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html."
160
163
  end
161
- @buffer << "For more information about routes, see the Rails guide: http://guides.rubyonrails.org/routing.html."
162
164
  end
163
165
 
164
- private
165
- def draw_section(routes)
166
- header_lengths = ["Prefix", "Verb", "URI Pattern"].map(&:length)
167
- name_width, verb_width, path_width = widths(routes).zip(header_lengths).map(&:max)
166
+ class Sheet < Base
167
+ def section_title(title)
168
+ @buffer << "\n#{title}:"
169
+ end
168
170
 
169
- routes.map do |r|
170
- "#{r[:name].rjust(name_width)} #{r[:verb].ljust(verb_width)} #{r[:path].ljust(path_width)} #{r[:reqs]}"
171
- end
171
+ def section(routes)
172
+ @buffer << draw_section(routes)
173
+ end
174
+
175
+ def header(routes)
176
+ @buffer << draw_header(routes)
172
177
  end
173
178
 
174
- def draw_header(routes)
175
- name_width, verb_width, path_width = widths(routes)
179
+ private
180
+ def draw_section(routes)
181
+ header_lengths = ["Prefix", "Verb", "URI Pattern"].map(&:length)
182
+ name_width, verb_width, path_width = widths(routes).zip(header_lengths).map(&:max)
183
+
184
+ routes.map do |r|
185
+ "#{r[:name].rjust(name_width)} #{r[:verb].ljust(verb_width)} #{r[:path].ljust(path_width)} #{r[:reqs]}"
186
+ end
187
+ end
188
+
189
+ def draw_header(routes)
190
+ name_width, verb_width, path_width = widths(routes)
176
191
 
177
- "#{"Prefix".rjust(name_width)} #{"Verb".ljust(verb_width)} #{"URI Pattern".ljust(path_width)} Controller#Action"
192
+ "#{"Prefix".rjust(name_width)} #{"Verb".ljust(verb_width)} #{"URI Pattern".ljust(path_width)} Controller#Action"
193
+ end
194
+
195
+ def widths(routes)
196
+ [routes.map { |r| r[:name].length }.max || 0,
197
+ routes.map { |r| r[:verb].length }.max || 0,
198
+ routes.map { |r| r[:path].length }.max || 0]
199
+ end
200
+ end
201
+
202
+ class Expanded < Base
203
+ def section_title(title)
204
+ @buffer << "\n#{"[ #{title} ]"}"
178
205
  end
179
206
 
180
- def widths(routes)
181
- [routes.map { |r| r[:name].length }.max || 0,
182
- routes.map { |r| r[:verb].length }.max || 0,
183
- routes.map { |r| r[:path].length }.max || 0]
207
+ def section(routes)
208
+ @buffer << draw_expanded_section(routes)
184
209
  end
210
+
211
+ private
212
+ def draw_expanded_section(routes)
213
+ routes.map.each_with_index do |r, i|
214
+ <<~MESSAGE.chomp
215
+ #{route_header(index: i + 1)}
216
+ Prefix | #{r[:name]}
217
+ Verb | #{r[:verb]}
218
+ URI | #{r[:path]}
219
+ Controller#Action | #{r[:reqs]}
220
+ MESSAGE
221
+ end
222
+ end
223
+
224
+ def route_header(index:)
225
+ console_width = IO.console_size.second
226
+ header_prefix = "--[ Route #{index} ]"
227
+ dash_remainder = [console_width - header_prefix.size, 0].max
228
+
229
+ "#{header_prefix}#{'-' * dash_remainder}"
230
+ end
231
+ end
185
232
  end
186
233
 
187
234
  class HtmlTableFormatter
@@ -203,16 +250,16 @@ module ActionDispatch
203
250
  end
204
251
 
205
252
  def no_routes(*)
206
- @buffer << <<-MESSAGE.strip_heredoc
253
+ @buffer << <<~MESSAGE
207
254
  <p>You don't have any routes defined!</p>
208
255
  <ul>
209
256
  <li>Please add some routes in <tt>config/routes.rb</tt>.</li>
210
257
  <li>
211
258
  For more information about routes, please see the Rails guide
212
- <a href="http://guides.rubyonrails.org/routing.html">Rails Routing from the Outside In</a>.
259
+ <a href="https://guides.rubyonrails.org/routing.html">Rails Routing from the Outside In</a>.
213
260
  </li>
214
261
  </ul>
215
- MESSAGE
262
+ MESSAGE
216
263
  end
217
264
 
218
265
  def result
@@ -50,7 +50,19 @@ module ActionDispatch
50
50
 
51
51
  private
52
52
  def constraint_args(constraint, request)
53
- constraint.arity == 1 ? [request] : [request.path_parameters, request]
53
+ arity = if constraint.respond_to?(:arity)
54
+ constraint.arity
55
+ else
56
+ constraint.method(:call).arity
57
+ end
58
+
59
+ if arity < 1
60
+ []
61
+ elsif arity == 1
62
+ [request]
63
+ else
64
+ [request.path_parameters, request]
65
+ end
54
66
  end
55
67
  end
56
68
 
@@ -58,17 +70,17 @@ module ActionDispatch
58
70
  ANCHOR_CHARACTERS_REGEX = %r{\A(\\A|\^)|(\\Z|\\z|\$)\Z}
59
71
  OPTIONAL_FORMAT_REGEX = %r{(?:\(\.:format\)+|\.:format|/)\Z}
60
72
 
61
- attr_reader :requirements, :defaults
62
- attr_reader :to, :default_controller, :default_action
63
- attr_reader :required_defaults, :ast
73
+ attr_reader :requirements, :defaults, :to, :default_controller,
74
+ :default_action, :required_defaults, :ast, :scope_options
64
75
 
65
76
  def self.build(scope, set, ast, controller, default_action, to, via, formatted, options_constraints, anchor, options)
66
77
  options = scope[:options].merge(options) if scope[:options]
67
78
 
68
79
  defaults = (scope[:defaults] || {}).dup
69
80
  scope_constraints = scope[:constraints] || {}
81
+ scope_options = scope[:options] || {}
70
82
 
71
- new set, ast, defaults, controller, default_action, scope[:module], to, formatted, scope_constraints, scope[:blocks] || [], via, options_constraints, anchor, options
83
+ new set, ast, defaults, controller, default_action, scope[:module], to, formatted, scope_constraints, scope_options, scope[:blocks] || [], via, options_constraints, anchor, options
72
84
  end
73
85
 
74
86
  def self.check_via(via)
@@ -99,17 +111,18 @@ module ActionDispatch
99
111
  format != false && path !~ OPTIONAL_FORMAT_REGEX
100
112
  end
101
113
 
102
- def initialize(set, ast, defaults, controller, default_action, modyoule, to, formatted, scope_constraints, blocks, via, options_constraints, anchor, options)
114
+ def initialize(set, ast, defaults, controller, default_action, modyoule, to, formatted, scope_constraints, scope_options, blocks, via, options_constraints, anchor, options)
103
115
  @defaults = defaults
104
116
  @set = set
105
117
 
106
- @to = to
107
- @default_controller = controller
108
- @default_action = default_action
118
+ @to = intern(to)
119
+ @default_controller = intern(controller)
120
+ @default_action = intern(default_action)
109
121
  @ast = ast
110
122
  @anchor = anchor
111
123
  @via = via
112
124
  @internal = options.delete(:internal)
125
+ @scope_options = scope_options
113
126
 
114
127
  path_params = ast.find_all(&:symbol?).map(&:to_sym)
115
128
 
@@ -148,17 +161,8 @@ module ActionDispatch
148
161
  end
149
162
 
150
163
  def make_route(name, precedence)
151
- route = Journey::Route.new(name,
152
- application,
153
- path,
154
- conditions,
155
- required_defaults,
156
- defaults,
157
- request_method,
158
- precedence,
159
- @internal)
160
-
161
- route
164
+ Journey::Route.new(name, application, path, conditions, required_defaults,
165
+ defaults, request_method, precedence, scope_options, @internal)
162
166
  end
163
167
 
164
168
  def application
@@ -219,6 +223,10 @@ module ActionDispatch
219
223
  private :build_path
220
224
 
221
225
  private
226
+ def intern(object)
227
+ object.is_a?(String) ? -object : object
228
+ end
229
+
222
230
  def add_wildcard_options(options, formatted, path_ast)
223
231
  # Add a constraint for wildcard route to make it non-greedy and match the
224
232
  # optional format part of the route by default.
@@ -279,7 +287,7 @@ module ActionDispatch
279
287
 
280
288
  def verify_regexp_requirements(requirements)
281
289
  requirements.each do |requirement|
282
- if requirement.source =~ ANCHOR_CHARACTERS_REGEX
290
+ if ANCHOR_CHARACTERS_REGEX.match?(requirement.source)
283
291
  raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}"
284
292
  end
285
293
 
@@ -308,8 +316,8 @@ module ActionDispatch
308
316
  def check_controller_and_action(path_params, controller, action)
309
317
  hash = check_part(:controller, controller, path_params, {}) do |part|
310
318
  translate_controller(part) {
311
- message = "'#{part}' is not a supported controller name. This can lead to potential routing problems.".dup
312
- message << " See http://guides.rubyonrails.org/routing.html#specifying-a-controller-to-use"
319
+ message = +"'#{part}' is not a supported controller name. This can lead to potential routing problems."
320
+ message << " See https://guides.rubyonrails.org/routing.html#specifying-a-controller-to-use"
313
321
 
314
322
  raise ArgumentError, message
315
323
  }
@@ -333,7 +341,7 @@ module ActionDispatch
333
341
  end
334
342
 
335
343
  def split_to(to)
336
- if to =~ /#/
344
+ if /#/.match?(to)
337
345
  to.split("#")
338
346
  else
339
347
  []
@@ -342,7 +350,7 @@ module ActionDispatch
342
350
 
343
351
  def add_controller_module(controller, modyoule)
344
352
  if modyoule && !controller.is_a?(Regexp)
345
- if controller =~ %r{\A/}
353
+ if %r{\A/}.match?(controller)
346
354
  controller[1..-1]
347
355
  else
348
356
  [modyoule, controller].compact.join("/")
@@ -354,7 +362,7 @@ module ActionDispatch
354
362
 
355
363
  def translate_controller(controller)
356
364
  return controller if Regexp === controller
357
- return controller.to_s if controller =~ /\A[a-z_0-9][a-z_0-9\/]*\z/
365
+ return controller.to_s if /\A[a-z_0-9][a-z_0-9\/]*\z/.match?(controller)
358
366
 
359
367
  yield
360
368
  end
@@ -390,7 +398,7 @@ module ActionDispatch
390
398
  # for root cases, where the latter is the correct one.
391
399
  def self.normalize_path(path)
392
400
  path = Journey::Router::Utils.normalize_path(path)
393
- path.gsub!(%r{/(\(+)/?}, '\1/') unless path =~ %r{^/(\(+[^)]+\)){1,}$}
401
+ path.gsub!(%r{/(\(+)/?}, '\1/') unless %r{^/(\(+[^)]+\)){1,}$}.match?(path)
394
402
  path
395
403
  end
396
404
 
@@ -553,10 +561,10 @@ module ActionDispatch
553
561
  #
554
562
  # match 'json_only', constraints: { format: 'json' }, via: :get
555
563
  #
556
- # class Whitelist
564
+ # class PermitList
557
565
  # def matches?(request) request.remote_ip == '1.2.3.4' end
558
566
  # end
559
- # match 'path', to: 'c#a', constraints: Whitelist.new, via: :get
567
+ # match 'path', to: 'c#a', constraints: PermitList.new, via: :get
560
568
  #
561
569
  # See <tt>Scoping#constraints</tt> for more examples with its scope
562
570
  # equivalent.
@@ -611,7 +619,7 @@ module ActionDispatch
611
619
  end
612
620
 
613
621
  raise ArgumentError, "A rack application must be specified" unless app.respond_to?(:call)
614
- raise ArgumentError, <<-MSG.strip_heredoc unless path
622
+ raise ArgumentError, <<~MSG unless path
615
623
  Must be called with mount point
616
624
 
617
625
  mount SomeRackApp, at: "some_route"
@@ -644,7 +652,7 @@ module ActionDispatch
644
652
 
645
653
  # Query if the following named route was already defined.
646
654
  def has_named_route?(name)
647
- @set.named_routes.key? name
655
+ @set.named_routes.key?(name)
648
656
  end
649
657
 
650
658
  private
@@ -668,7 +676,7 @@ module ActionDispatch
668
676
 
669
677
  script_namer = ->(options) do
670
678
  prefix_options = options.slice(*_route.segment_keys)
671
- prefix_options[:relative_url_root] = "".freeze
679
+ prefix_options[:relative_url_root] = ""
672
680
 
673
681
  if options[:_recall]
674
682
  prefix_options.reverse_merge!(options[:_recall].slice(*_route.segment_keys))
@@ -1138,6 +1146,10 @@ module ActionDispatch
1138
1146
  attr_reader :controller, :path, :param
1139
1147
 
1140
1148
  def initialize(entities, api_only, shallow, options = {})
1149
+ if options[:param].to_s.include?(":")
1150
+ raise ArgumentError, ":param option can't contain colons"
1151
+ end
1152
+
1141
1153
  @name = entities.to_s
1142
1154
  @path = (options[:path] || @name).to_s
1143
1155
  @controller = (options[:controller] || @name).to_s
@@ -1159,10 +1171,16 @@ module ActionDispatch
1159
1171
  end
1160
1172
 
1161
1173
  def actions
1174
+ if @except
1175
+ available_actions - Array(@except).map(&:to_sym)
1176
+ else
1177
+ available_actions
1178
+ end
1179
+ end
1180
+
1181
+ def available_actions
1162
1182
  if @only
1163
1183
  Array(@only).map(&:to_sym)
1164
- elsif @except
1165
- default_actions - Array(@except).map(&:to_sym)
1166
1184
  else
1167
1185
  default_actions
1168
1186
  end
@@ -1389,6 +1407,8 @@ module ActionDispatch
1389
1407
  # as a comment on a blog post like <tt>/posts/a-long-permalink/comments/1234</tt>
1390
1408
  # to be shortened to just <tt>/comments/1234</tt>.
1391
1409
  #
1410
+ # Set <tt>shallow: false</tt> on a child resource to ignore a parent's shallow parameter.
1411
+ #
1392
1412
  # [:shallow_path]
1393
1413
  # Prefixes nested shallow routes with the specified path.
1394
1414
  #
@@ -1431,6 +1451,9 @@ module ActionDispatch
1431
1451
  # Allows you to specify the default value for optional +format+
1432
1452
  # segment or disable it by supplying +false+.
1433
1453
  #
1454
+ # [:param]
1455
+ # Allows you to override the default param name of +:id+ in the URL.
1456
+ #
1434
1457
  # === Examples
1435
1458
  #
1436
1459
  # # routes call <tt>Admin::PostsController</tt>
@@ -1588,7 +1611,7 @@ module ActionDispatch
1588
1611
  when Symbol
1589
1612
  options[:action] = to
1590
1613
  when String
1591
- if to =~ /#/
1614
+ if /#/.match?(to)
1592
1615
  options[:to] = to
1593
1616
  else
1594
1617
  options[:controller] = to
@@ -1645,7 +1668,6 @@ module ActionDispatch
1645
1668
  end
1646
1669
 
1647
1670
  private
1648
-
1649
1671
  def parent_resource
1650
1672
  @scope[:scope_level_resource]
1651
1673
  end
@@ -1656,7 +1678,8 @@ module ActionDispatch
1656
1678
  return true
1657
1679
  end
1658
1680
 
1659
- if options.delete(:shallow)
1681
+ if options[:shallow]
1682
+ options.delete(:shallow)
1660
1683
  shallow do
1661
1684
  send(method, resources.pop, options, &block)
1662
1685
  end
@@ -1914,7 +1937,7 @@ module ActionDispatch
1914
1937
 
1915
1938
  default_action = options.delete(:action) || @scope[:action]
1916
1939
 
1917
- if action =~ /^[\w\-\/]+$/
1940
+ if /^[\w\-\/]+$/.match?(action)
1918
1941
  default_action ||= action.tr("-", "_") unless action.include?("/")
1919
1942
  else
1920
1943
  action = nil
@@ -1934,9 +1957,7 @@ module ActionDispatch
1934
1957
  end
1935
1958
 
1936
1959
  def match_root_route(options)
1937
- name = has_named_route?(name_for_action(:root, nil)) ? nil : :root
1938
- args = ["/", { as: name, via: :get }.merge!(options)]
1939
-
1960
+ args = ["/", { as: :root, via: :get }.merge(options)]
1940
1961
  match(*args)
1941
1962
  end
1942
1963
  end
@@ -2052,7 +2073,7 @@ module ActionDispatch
2052
2073
  # of routing helpers, e.g:
2053
2074
  #
2054
2075
  # direct :homepage do
2055
- # "http://www.rubyonrails.org"
2076
+ # "https://rubyonrails.org"
2056
2077
  # end
2057
2078
  #
2058
2079
  # direct :commentable do |model|