actionpack 4.2.10 → 7.2.0.rc1

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

Potentially problematic release.


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

Files changed (202) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +86 -600
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +13 -14
  5. data/lib/abstract_controller/asset_paths.rb +5 -1
  6. data/lib/abstract_controller/base.rb +166 -136
  7. data/lib/abstract_controller/caching/fragments.rb +149 -0
  8. data/lib/abstract_controller/caching.rb +68 -0
  9. data/lib/abstract_controller/callbacks.rb +126 -57
  10. data/lib/abstract_controller/collector.rb +13 -15
  11. data/lib/abstract_controller/deprecator.rb +9 -0
  12. data/lib/abstract_controller/error.rb +8 -0
  13. data/lib/abstract_controller/helpers.rb +181 -132
  14. data/lib/abstract_controller/logger.rb +5 -1
  15. data/lib/abstract_controller/railties/routes_helpers.rb +10 -3
  16. data/lib/abstract_controller/rendering.rb +56 -56
  17. data/lib/abstract_controller/translation.rb +29 -15
  18. data/lib/abstract_controller/url_for.rb +15 -11
  19. data/lib/abstract_controller.rb +21 -5
  20. data/lib/action_controller/api/api_rendering.rb +18 -0
  21. data/lib/action_controller/api.rb +154 -0
  22. data/lib/action_controller/base.rb +219 -155
  23. data/lib/action_controller/caching.rb +28 -68
  24. data/lib/action_controller/deprecator.rb +9 -0
  25. data/lib/action_controller/form_builder.rb +55 -0
  26. data/lib/action_controller/log_subscriber.rb +35 -22
  27. data/lib/action_controller/metal/allow_browser.rb +119 -0
  28. data/lib/action_controller/metal/basic_implicit_render.rb +17 -0
  29. data/lib/action_controller/metal/conditional_get.rb +259 -122
  30. data/lib/action_controller/metal/content_security_policy.rb +86 -0
  31. data/lib/action_controller/metal/cookies.rb +9 -5
  32. data/lib/action_controller/metal/data_streaming.rb +87 -104
  33. data/lib/action_controller/metal/default_headers.rb +21 -0
  34. data/lib/action_controller/metal/etag_with_flash.rb +22 -0
  35. data/lib/action_controller/metal/etag_with_template_digest.rb +35 -26
  36. data/lib/action_controller/metal/exceptions.rb +71 -24
  37. data/lib/action_controller/metal/flash.rb +26 -19
  38. data/lib/action_controller/metal/head.rb +45 -36
  39. data/lib/action_controller/metal/helpers.rb +80 -64
  40. data/lib/action_controller/metal/http_authentication.rb +297 -244
  41. data/lib/action_controller/metal/implicit_render.rb +57 -9
  42. data/lib/action_controller/metal/instrumentation.rb +76 -64
  43. data/lib/action_controller/metal/live.rb +238 -176
  44. data/lib/action_controller/metal/logging.rb +22 -0
  45. data/lib/action_controller/metal/mime_responds.rb +177 -166
  46. data/lib/action_controller/metal/parameter_encoding.rb +84 -0
  47. data/lib/action_controller/metal/params_wrapper.rb +145 -118
  48. data/lib/action_controller/metal/permissions_policy.rb +38 -0
  49. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  50. data/lib/action_controller/metal/redirecting.rb +203 -64
  51. data/lib/action_controller/metal/renderers.rb +108 -65
  52. data/lib/action_controller/metal/rendering.rb +216 -56
  53. data/lib/action_controller/metal/request_forgery_protection.rb +496 -163
  54. data/lib/action_controller/metal/rescue.rb +19 -21
  55. data/lib/action_controller/metal/streaming.rb +179 -138
  56. data/lib/action_controller/metal/strong_parameters.rb +1058 -382
  57. data/lib/action_controller/metal/testing.rb +11 -17
  58. data/lib/action_controller/metal/url_for.rb +37 -21
  59. data/lib/action_controller/metal.rb +236 -138
  60. data/lib/action_controller/railtie.rb +89 -11
  61. data/lib/action_controller/railties/helpers.rb +5 -1
  62. data/lib/action_controller/renderer.rb +161 -0
  63. data/lib/action_controller/template_assertions.rb +13 -0
  64. data/lib/action_controller/test_case.rb +425 -497
  65. data/lib/action_controller.rb +44 -22
  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 +119 -63
  69. data/lib/action_dispatch/http/content_disposition.rb +47 -0
  70. data/lib/action_dispatch/http/content_security_policy.rb +364 -0
  71. data/lib/action_dispatch/http/filter_parameters.rb +36 -34
  72. data/lib/action_dispatch/http/filter_redirect.rb +24 -12
  73. data/lib/action_dispatch/http/headers.rb +66 -31
  74. data/lib/action_dispatch/http/mime_negotiation.rb +106 -75
  75. data/lib/action_dispatch/http/mime_type.rb +196 -136
  76. data/lib/action_dispatch/http/mime_types.rb +25 -7
  77. data/lib/action_dispatch/http/parameters.rb +97 -45
  78. data/lib/action_dispatch/http/permissions_policy.rb +187 -0
  79. data/lib/action_dispatch/http/rack_cache.rb +6 -0
  80. data/lib/action_dispatch/http/request.rb +299 -170
  81. data/lib/action_dispatch/http/response.rb +311 -160
  82. data/lib/action_dispatch/http/upload.rb +52 -23
  83. data/lib/action_dispatch/http/url.rb +201 -125
  84. data/lib/action_dispatch/journey/formatter.rb +110 -50
  85. data/lib/action_dispatch/journey/gtg/builder.rb +37 -50
  86. data/lib/action_dispatch/journey/gtg/simulator.rb +20 -17
  87. data/lib/action_dispatch/journey/gtg/transition_table.rb +96 -36
  88. data/lib/action_dispatch/journey/nfa/dot.rb +5 -14
  89. data/lib/action_dispatch/journey/nodes/node.rb +100 -20
  90. data/lib/action_dispatch/journey/parser.rb +19 -17
  91. data/lib/action_dispatch/journey/parser.y +4 -3
  92. data/lib/action_dispatch/journey/parser_extras.rb +14 -4
  93. data/lib/action_dispatch/journey/path/pattern.rb +79 -63
  94. data/lib/action_dispatch/journey/route.rb +108 -44
  95. data/lib/action_dispatch/journey/router/utils.rb +41 -29
  96. data/lib/action_dispatch/journey/router.rb +64 -57
  97. data/lib/action_dispatch/journey/routes.rb +23 -21
  98. data/lib/action_dispatch/journey/scanner.rb +28 -17
  99. data/lib/action_dispatch/journey/visitors.rb +100 -54
  100. data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
  101. data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
  102. data/lib/action_dispatch/journey.rb +7 -5
  103. data/lib/action_dispatch/log_subscriber.rb +25 -0
  104. data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
  105. data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
  106. data/lib/action_dispatch/middleware/callbacks.rb +7 -6
  107. data/lib/action_dispatch/middleware/cookies.rb +471 -328
  108. data/lib/action_dispatch/middleware/debug_exceptions.rb +149 -66
  109. data/lib/action_dispatch/middleware/debug_locks.rb +129 -0
  110. data/lib/action_dispatch/middleware/debug_view.rb +73 -0
  111. data/lib/action_dispatch/middleware/exception_wrapper.rb +275 -73
  112. data/lib/action_dispatch/middleware/executor.rb +32 -0
  113. data/lib/action_dispatch/middleware/flash.rb +143 -101
  114. data/lib/action_dispatch/middleware/host_authorization.rb +171 -0
  115. data/lib/action_dispatch/middleware/public_exceptions.rb +36 -27
  116. data/lib/action_dispatch/middleware/reloader.rb +10 -92
  117. data/lib/action_dispatch/middleware/remote_ip.rb +133 -107
  118. data/lib/action_dispatch/middleware/request_id.rb +29 -15
  119. data/lib/action_dispatch/middleware/server_timing.rb +78 -0
  120. data/lib/action_dispatch/middleware/session/abstract_store.rb +49 -27
  121. data/lib/action_dispatch/middleware/session/cache_store.rb +33 -16
  122. data/lib/action_dispatch/middleware/session/cookie_store.rb +86 -80
  123. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -3
  124. data/lib/action_dispatch/middleware/show_exceptions.rb +66 -36
  125. data/lib/action_dispatch/middleware/ssl.rb +134 -36
  126. data/lib/action_dispatch/middleware/stack.rb +109 -44
  127. data/lib/action_dispatch/middleware/static.rb +159 -90
  128. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  129. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  130. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +7 -24
  132. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  133. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +36 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +46 -36
  136. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +12 -0
  137. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +9 -0
  138. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -7
  139. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +3 -3
  140. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
  141. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +16 -0
  142. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +139 -15
  143. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +23 -0
  144. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  145. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +6 -6
  146. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +7 -7
  147. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +9 -9
  148. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
  149. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
  150. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
  151. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +7 -4
  152. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +125 -93
  153. data/lib/action_dispatch/railtie.rb +44 -16
  154. data/lib/action_dispatch/request/session.rb +159 -69
  155. data/lib/action_dispatch/request/utils.rb +97 -23
  156. data/lib/action_dispatch/routing/endpoint.rb +11 -2
  157. data/lib/action_dispatch/routing/inspector.rb +195 -106
  158. data/lib/action_dispatch/routing/mapper.rb +1338 -955
  159. data/lib/action_dispatch/routing/polymorphic_routes.rb +234 -201
  160. data/lib/action_dispatch/routing/redirection.rb +78 -51
  161. data/lib/action_dispatch/routing/route_set.rb +460 -374
  162. data/lib/action_dispatch/routing/routes_proxy.rb +36 -12
  163. data/lib/action_dispatch/routing/url_for.rb +172 -124
  164. data/lib/action_dispatch/routing.rb +159 -158
  165. data/lib/action_dispatch/system_test_case.rb +206 -0
  166. data/lib/action_dispatch/system_testing/browser.rb +84 -0
  167. data/lib/action_dispatch/system_testing/driver.rb +85 -0
  168. data/lib/action_dispatch/system_testing/server.rb +33 -0
  169. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +164 -0
  170. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +23 -0
  171. data/lib/action_dispatch/testing/assertion_response.rb +48 -0
  172. data/lib/action_dispatch/testing/assertions/response.rb +71 -39
  173. data/lib/action_dispatch/testing/assertions/routing.rb +228 -103
  174. data/lib/action_dispatch/testing/assertions.rb +9 -6
  175. data/lib/action_dispatch/testing/integration.rb +486 -306
  176. data/lib/action_dispatch/testing/request_encoder.rb +60 -0
  177. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  178. data/lib/action_dispatch/testing/test_process.rb +35 -22
  179. data/lib/action_dispatch/testing/test_request.rb +29 -34
  180. data/lib/action_dispatch/testing/test_response.rb +48 -15
  181. data/lib/action_dispatch.rb +82 -40
  182. data/lib/action_pack/gem_version.rb +8 -4
  183. data/lib/action_pack/version.rb +6 -2
  184. data/lib/action_pack.rb +21 -18
  185. metadata +146 -56
  186. data/lib/action_controller/caching/fragments.rb +0 -103
  187. data/lib/action_controller/metal/force_ssl.rb +0 -97
  188. data/lib/action_controller/metal/hide_actions.rb +0 -40
  189. data/lib/action_controller/metal/rack_delegation.rb +0 -32
  190. data/lib/action_controller/middleware.rb +0 -39
  191. data/lib/action_controller/model_naming.rb +0 -12
  192. data/lib/action_dispatch/http/parameter_filter.rb +0 -72
  193. data/lib/action_dispatch/journey/backwards.rb +0 -5
  194. data/lib/action_dispatch/journey/nfa/builder.rb +0 -76
  195. data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
  196. data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -163
  197. data/lib/action_dispatch/journey/router/strexp.rb +0 -27
  198. data/lib/action_dispatch/middleware/params_parser.rb +0 -60
  199. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +0 -27
  200. data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
  201. data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
  202. data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,11 +1,28 @@
1
- require 'delegate'
2
- require 'active_support/core_ext/string/strip'
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ require "delegate"
6
+ require "io/console/size"
3
7
 
4
8
  module ActionDispatch
5
9
  module Routing
6
- class RouteWrapper < SimpleDelegator
10
+ class RouteWrapper < SimpleDelegator # :nodoc:
11
+ def matches_filter?(filter, value)
12
+ return __getobj__.path.match(value) if filter == :exact_path_match
13
+
14
+ value.match?(public_send(filter))
15
+ end
16
+
7
17
  def endpoint
8
- app.dispatcher? ? "#{controller}##{action}" : rack_app.inspect
18
+ case
19
+ when app.dispatcher?
20
+ "#{controller}##{action}"
21
+ when rack_app.is_a?(Proc)
22
+ "Inline handler (Proc/Lambda)"
23
+ else
24
+ rack_app.inspect
25
+ end
9
26
  end
10
27
 
11
28
  def constraints
@@ -13,11 +30,7 @@ module ActionDispatch
13
30
  end
14
31
 
15
32
  def rack_app
16
- app.app
17
- end
18
-
19
- def verb
20
- super.source.gsub(/[$^]/, '')
33
+ app.rack_app
21
34
  end
22
35
 
23
36
  def path
@@ -28,23 +41,6 @@ module ActionDispatch
28
41
  super.to_s
29
42
  end
30
43
 
31
- def regexp
32
- __getobj__.path.to_regexp
33
- end
34
-
35
- def json_regexp
36
- str = regexp.inspect.
37
- sub('\\A' , '^').
38
- sub('\\Z' , '$').
39
- sub('\\z' , '$').
40
- sub(/^\// , '').
41
- sub(/\/[a-z]*$/ , '').
42
- gsub(/\(\?#.+\)/ , '').
43
- gsub(/\(\?-\w+:/ , '(').
44
- gsub(/\s/ , '')
45
- Regexp.new(str).source
46
- end
47
-
48
44
  def reqs
49
45
  @reqs ||= begin
50
46
  reqs = endpoint
@@ -54,39 +50,37 @@ module ActionDispatch
54
50
  end
55
51
 
56
52
  def controller
57
- requirements[:controller] || ':controller'
53
+ parts.include?(:controller) ? ":controller" : requirements[:controller]
58
54
  end
59
55
 
60
56
  def action
61
- requirements[:action] || ':action'
57
+ parts.include?(:action) ? ":action" : requirements[:action]
62
58
  end
63
59
 
64
60
  def internal?
65
- controller.to_s =~ %r{\Arails/(info|mailers|welcome)} || path =~ %r{\A#{Rails.application.config.assets.prefix}\z}
61
+ internal
66
62
  end
67
63
 
68
64
  def engine?
69
- rack_app.respond_to?(:routes)
65
+ app.engine?
70
66
  end
71
67
  end
72
68
 
73
69
  ##
74
70
  # This class is just used for displaying route information when someone
75
- # executes `rake routes` or looks at the RoutingError page.
76
- # People should not use this class.
71
+ # executes `bin/rails routes` or looks at the RoutingError page. People should
72
+ # not use this class.
77
73
  class RoutesInspector # :nodoc:
78
74
  def initialize(routes)
79
75
  @engines = {}
80
76
  @routes = routes
81
77
  end
82
78
 
83
- def format(formatter, filter = nil)
84
- routes_to_display = filter_routes(filter)
85
-
79
+ def format(formatter, filter = {})
80
+ routes_to_display = filter_routes(normalize_filter(filter))
86
81
  routes = collect_routes(routes_to_display)
87
-
88
82
  if routes.none?
89
- formatter.no_routes
83
+ formatter.no_routes(collect_routes(@routes), filter)
90
84
  return formatter.result
91
85
  end
92
86
 
@@ -102,95 +96,190 @@ module ActionDispatch
102
96
  end
103
97
 
104
98
  private
105
-
106
- def filter_routes(filter)
107
- if filter
108
- @routes.select { |route| route.defaults[:controller] == filter }
109
- else
110
- @routes
99
+ def normalize_filter(filter)
100
+ if filter[:controller]
101
+ { controller: /#{filter[:controller].underscore.sub(/_?controller\z/, "")}/ }
102
+ elsif filter[:grep]
103
+ grep_pattern = Regexp.new(filter[:grep])
104
+ path = URI::DEFAULT_PARSER.escape(filter[:grep])
105
+ normalized_path = ("/" + path).squeeze("/")
106
+
107
+ {
108
+ controller: grep_pattern,
109
+ action: grep_pattern,
110
+ verb: grep_pattern,
111
+ name: grep_pattern,
112
+ path: grep_pattern,
113
+ exact_path_match: normalized_path,
114
+ }
115
+ end
111
116
  end
112
- end
113
117
 
114
- def collect_routes(routes)
115
- routes.collect do |route|
116
- RouteWrapper.new(route)
117
- end.reject do |route|
118
- route.internal?
119
- end.collect do |route|
120
- collect_engine_routes(route)
118
+ def filter_routes(filter)
119
+ if filter
120
+ @routes.select do |route|
121
+ route_wrapper = RouteWrapper.new(route)
122
+ filter.any? { |filter_type, value| route_wrapper.matches_filter?(filter_type, value) }
123
+ end
124
+ else
125
+ @routes
126
+ end
127
+ end
121
128
 
122
- { name: route.name,
123
- verb: route.verb,
124
- path: route.path,
125
- reqs: route.reqs,
126
- regexp: route.json_regexp }
129
+ def collect_routes(routes)
130
+ routes.collect do |route|
131
+ RouteWrapper.new(route)
132
+ end.reject(&:internal?).collect do |route|
133
+ collect_engine_routes(route)
134
+
135
+ { name: route.name,
136
+ verb: route.verb,
137
+ path: route.path,
138
+ reqs: route.reqs,
139
+ source_location: route.source_location }
140
+ end
127
141
  end
128
- end
129
142
 
130
- def collect_engine_routes(route)
131
- name = route.endpoint
132
- return unless route.engine?
133
- return if @engines[name]
143
+ def collect_engine_routes(route)
144
+ name = route.endpoint
145
+ return unless route.engine?
146
+ return if @engines[name]
134
147
 
135
- routes = route.rack_app.routes
136
- if routes.is_a?(ActionDispatch::Routing::RouteSet)
137
- @engines[name] = collect_routes(routes.routes)
148
+ routes = route.rack_app.routes
149
+ if routes.is_a?(ActionDispatch::Routing::RouteSet)
150
+ @engines[name] = collect_routes(routes.routes)
151
+ end
138
152
  end
139
- end
140
153
  end
141
154
 
142
- class ConsoleFormatter
143
- def initialize
144
- @buffer = []
145
- end
155
+ module ConsoleFormatter
156
+ class Base
157
+ def initialize
158
+ @buffer = []
159
+ end
146
160
 
147
- def result
148
- @buffer.join("\n")
149
- end
161
+ def result
162
+ @buffer.join("\n")
163
+ end
150
164
 
151
- def section_title(title)
152
- @buffer << "\n#{title}:"
153
- end
165
+ def section_title(title)
166
+ end
154
167
 
155
- def section(routes)
156
- @buffer << draw_section(routes)
157
- end
168
+ def section(routes)
169
+ end
158
170
 
159
- def header(routes)
160
- @buffer << draw_header(routes)
171
+ def header(routes)
172
+ end
173
+
174
+ def no_routes(routes, filter)
175
+ @buffer <<
176
+ if routes.none?
177
+ <<~MESSAGE
178
+ You don't have any routes defined!
179
+
180
+ Please add some routes in config/routes.rb.
181
+ MESSAGE
182
+ elsif filter.key?(:controller)
183
+ "No routes were found for this controller."
184
+ elsif filter.key?(:grep)
185
+ "No routes were found for this grep pattern."
186
+ end
187
+
188
+ @buffer << "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html."
189
+ end
161
190
  end
162
191
 
163
- def no_routes
164
- @buffer << <<-MESSAGE.strip_heredoc
165
- You don't have any routes defined!
192
+ class Sheet < Base
193
+ def section_title(title)
194
+ @buffer << "\n#{title}:"
195
+ end
166
196
 
167
- Please add some routes in config/routes.rb.
197
+ def section(routes)
198
+ @buffer << draw_section(routes)
199
+ end
168
200
 
169
- For more information about routes, see the Rails guide: http://guides.rubyonrails.org/routing.html.
170
- MESSAGE
171
- end
201
+ def header(routes)
202
+ @buffer << draw_header(routes)
203
+ end
172
204
 
173
- private
174
- def draw_section(routes)
175
- header_lengths = ['Prefix', 'Verb', 'URI Pattern'].map(&:length)
176
- name_width, verb_width, path_width = widths(routes).zip(header_lengths).map(&:max)
205
+ private
206
+ def draw_section(routes)
207
+ header_lengths = ["Prefix", "Verb", "URI Pattern"].map(&:length)
208
+ name_width, verb_width, path_width = widths(routes).zip(header_lengths).map(&:max)
177
209
 
178
- routes.map do |r|
179
- "#{r[:name].rjust(name_width)} #{r[:verb].ljust(verb_width)} #{r[:path].ljust(path_width)} #{r[:reqs]}"
210
+ routes.map do |r|
211
+ "#{r[:name].rjust(name_width)} #{r[:verb].ljust(verb_width)} #{r[:path].ljust(path_width)} #{r[:reqs]}"
212
+ end
180
213
  end
214
+
215
+ def draw_header(routes)
216
+ name_width, verb_width, path_width = widths(routes)
217
+
218
+ "#{"Prefix".rjust(name_width)} #{"Verb".ljust(verb_width)} #{"URI Pattern".ljust(path_width)} Controller#Action"
219
+ end
220
+
221
+ def widths(routes)
222
+ [routes.map { |r| r[:name].length }.max || 0,
223
+ routes.map { |r| r[:verb].length }.max || 0,
224
+ routes.map { |r| r[:path].length }.max || 0]
225
+ end
226
+ end
227
+
228
+ class Expanded < Base
229
+ def initialize(width: IO.console_size[1])
230
+ @width = width
231
+ super()
181
232
  end
182
233
 
183
- def draw_header(routes)
184
- name_width, verb_width, path_width = widths(routes)
234
+ def section_title(title)
235
+ @buffer << "\n#{"[ #{title} ]"}"
236
+ end
185
237
 
186
- "#{"Prefix".rjust(name_width)} #{"Verb".ljust(verb_width)} #{"URI Pattern".ljust(path_width)} Controller#Action"
238
+ def section(routes)
239
+ @buffer << draw_expanded_section(routes)
187
240
  end
188
241
 
189
- def widths(routes)
190
- [routes.map { |r| r[:name].length }.max || 0,
191
- routes.map { |r| r[:verb].length }.max || 0,
192
- routes.map { |r| r[:path].length }.max || 0]
242
+ private
243
+ def draw_expanded_section(routes)
244
+ routes.map.each_with_index do |r, i|
245
+ route_rows = <<~MESSAGE.chomp
246
+ #{route_header(index: i + 1)}
247
+ Prefix | #{r[:name]}
248
+ Verb | #{r[:verb]}
249
+ URI | #{r[:path]}
250
+ Controller#Action | #{r[:reqs]}
251
+ MESSAGE
252
+ source_location = "\nSource Location | #{r[:source_location]}"
253
+ route_rows += source_location if r[:source_location].present?
254
+ route_rows
255
+ end
256
+ end
257
+
258
+ def route_header(index:)
259
+ "--[ Route #{index} ]".ljust(@width, "-")
260
+ end
261
+ end
262
+
263
+ class Unused < Sheet
264
+ def header(routes)
265
+ @buffer << <<~MSG
266
+ Found #{routes.count} unused #{"route".pluralize(routes.count)}:
267
+ MSG
268
+
269
+ super
193
270
  end
271
+
272
+ def no_routes(routes, filter)
273
+ @buffer <<
274
+ if filter.none?
275
+ "No unused routes found."
276
+ elsif filter.key?(:controller)
277
+ "No unused routes found for this controller."
278
+ elsif filter.key?(:grep)
279
+ "No unused routes found for this grep pattern."
280
+ end
281
+ end
282
+ end
194
283
  end
195
284
 
196
285
  class HtmlTableFormatter
@@ -200,28 +289,28 @@ module ActionDispatch
200
289
  end
201
290
 
202
291
  def section_title(title)
203
- @buffer << %(<tr><th colspan="4">#{title}</th></tr>)
292
+ @buffer << %(<tr><th colspan="5">#{title}</th></tr>)
204
293
  end
205
294
 
206
295
  def section(routes)
207
296
  @buffer << @view.render(partial: "routes/route", collection: routes)
208
297
  end
209
298
 
210
- # the header is part of the HTML page, so we don't construct it here.
299
+ # The header is part of the HTML page, so we don't construct it here.
211
300
  def header(routes)
212
301
  end
213
302
 
214
- def no_routes
215
- @buffer << <<-MESSAGE.strip_heredoc
303
+ def no_routes(*)
304
+ @buffer << <<~MESSAGE
216
305
  <p>You don't have any routes defined!</p>
217
306
  <ul>
218
307
  <li>Please add some routes in <tt>config/routes.rb</tt>.</li>
219
308
  <li>
220
309
  For more information about routes, please see the Rails guide
221
- <a href="http://guides.rubyonrails.org/routing.html">Rails Routing from the Outside In</a>.
310
+ <a href="https://guides.rubyonrails.org/routing.html">Rails Routing from the Outside In</a>.
222
311
  </li>
223
312
  </ul>
224
- MESSAGE
313
+ MESSAGE
225
314
  end
226
315
 
227
316
  def result