actionpack 5.2.3

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 (170) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +429 -0
  3. data/MIT-LICENSE +21 -0
  4. data/README.rdoc +57 -0
  5. data/lib/abstract_controller.rb +27 -0
  6. data/lib/abstract_controller/asset_paths.rb +12 -0
  7. data/lib/abstract_controller/base.rb +265 -0
  8. data/lib/abstract_controller/caching.rb +66 -0
  9. data/lib/abstract_controller/caching/fragments.rb +166 -0
  10. data/lib/abstract_controller/callbacks.rb +212 -0
  11. data/lib/abstract_controller/collector.rb +43 -0
  12. data/lib/abstract_controller/error.rb +6 -0
  13. data/lib/abstract_controller/helpers.rb +194 -0
  14. data/lib/abstract_controller/logger.rb +14 -0
  15. data/lib/abstract_controller/railties/routes_helpers.rb +20 -0
  16. data/lib/abstract_controller/rendering.rb +127 -0
  17. data/lib/abstract_controller/translation.rb +31 -0
  18. data/lib/abstract_controller/url_for.rb +35 -0
  19. data/lib/action_controller.rb +66 -0
  20. data/lib/action_controller/api.rb +149 -0
  21. data/lib/action_controller/api/api_rendering.rb +16 -0
  22. data/lib/action_controller/base.rb +276 -0
  23. data/lib/action_controller/caching.rb +46 -0
  24. data/lib/action_controller/form_builder.rb +50 -0
  25. data/lib/action_controller/log_subscriber.rb +78 -0
  26. data/lib/action_controller/metal.rb +256 -0
  27. data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
  28. data/lib/action_controller/metal/conditional_get.rb +274 -0
  29. data/lib/action_controller/metal/content_security_policy.rb +52 -0
  30. data/lib/action_controller/metal/cookies.rb +16 -0
  31. data/lib/action_controller/metal/data_streaming.rb +152 -0
  32. data/lib/action_controller/metal/etag_with_flash.rb +18 -0
  33. data/lib/action_controller/metal/etag_with_template_digest.rb +57 -0
  34. data/lib/action_controller/metal/exceptions.rb +53 -0
  35. data/lib/action_controller/metal/flash.rb +61 -0
  36. data/lib/action_controller/metal/force_ssl.rb +99 -0
  37. data/lib/action_controller/metal/head.rb +60 -0
  38. data/lib/action_controller/metal/helpers.rb +123 -0
  39. data/lib/action_controller/metal/http_authentication.rb +519 -0
  40. data/lib/action_controller/metal/implicit_render.rb +73 -0
  41. data/lib/action_controller/metal/instrumentation.rb +107 -0
  42. data/lib/action_controller/metal/live.rb +312 -0
  43. data/lib/action_controller/metal/mime_responds.rb +313 -0
  44. data/lib/action_controller/metal/parameter_encoding.rb +51 -0
  45. data/lib/action_controller/metal/params_wrapper.rb +293 -0
  46. data/lib/action_controller/metal/redirecting.rb +133 -0
  47. data/lib/action_controller/metal/renderers.rb +181 -0
  48. data/lib/action_controller/metal/rendering.rb +122 -0
  49. data/lib/action_controller/metal/request_forgery_protection.rb +445 -0
  50. data/lib/action_controller/metal/rescue.rb +28 -0
  51. data/lib/action_controller/metal/streaming.rb +223 -0
  52. data/lib/action_controller/metal/strong_parameters.rb +1086 -0
  53. data/lib/action_controller/metal/testing.rb +16 -0
  54. data/lib/action_controller/metal/url_for.rb +58 -0
  55. data/lib/action_controller/railtie.rb +89 -0
  56. data/lib/action_controller/railties/helpers.rb +24 -0
  57. data/lib/action_controller/renderer.rb +117 -0
  58. data/lib/action_controller/template_assertions.rb +11 -0
  59. data/lib/action_controller/test_case.rb +629 -0
  60. data/lib/action_dispatch.rb +112 -0
  61. data/lib/action_dispatch/http/cache.rb +222 -0
  62. data/lib/action_dispatch/http/content_security_policy.rb +272 -0
  63. data/lib/action_dispatch/http/filter_parameters.rb +84 -0
  64. data/lib/action_dispatch/http/filter_redirect.rb +37 -0
  65. data/lib/action_dispatch/http/headers.rb +132 -0
  66. data/lib/action_dispatch/http/mime_negotiation.rb +175 -0
  67. data/lib/action_dispatch/http/mime_type.rb +342 -0
  68. data/lib/action_dispatch/http/mime_types.rb +50 -0
  69. data/lib/action_dispatch/http/parameter_filter.rb +86 -0
  70. data/lib/action_dispatch/http/parameters.rb +126 -0
  71. data/lib/action_dispatch/http/rack_cache.rb +63 -0
  72. data/lib/action_dispatch/http/request.rb +430 -0
  73. data/lib/action_dispatch/http/response.rb +519 -0
  74. data/lib/action_dispatch/http/upload.rb +84 -0
  75. data/lib/action_dispatch/http/url.rb +350 -0
  76. data/lib/action_dispatch/journey.rb +7 -0
  77. data/lib/action_dispatch/journey/formatter.rb +189 -0
  78. data/lib/action_dispatch/journey/gtg/builder.rb +164 -0
  79. data/lib/action_dispatch/journey/gtg/simulator.rb +41 -0
  80. data/lib/action_dispatch/journey/gtg/transition_table.rb +158 -0
  81. data/lib/action_dispatch/journey/nfa/builder.rb +78 -0
  82. data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
  83. data/lib/action_dispatch/journey/nfa/simulator.rb +49 -0
  84. data/lib/action_dispatch/journey/nfa/transition_table.rb +120 -0
  85. data/lib/action_dispatch/journey/nodes/node.rb +140 -0
  86. data/lib/action_dispatch/journey/parser.rb +199 -0
  87. data/lib/action_dispatch/journey/parser.y +50 -0
  88. data/lib/action_dispatch/journey/parser_extras.rb +31 -0
  89. data/lib/action_dispatch/journey/path/pattern.rb +198 -0
  90. data/lib/action_dispatch/journey/route.rb +203 -0
  91. data/lib/action_dispatch/journey/router.rb +156 -0
  92. data/lib/action_dispatch/journey/router/utils.rb +102 -0
  93. data/lib/action_dispatch/journey/routes.rb +82 -0
  94. data/lib/action_dispatch/journey/scanner.rb +64 -0
  95. data/lib/action_dispatch/journey/visitors.rb +268 -0
  96. data/lib/action_dispatch/journey/visualizer/fsm.css +30 -0
  97. data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
  98. data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
  99. data/lib/action_dispatch/middleware/callbacks.rb +36 -0
  100. data/lib/action_dispatch/middleware/cookies.rb +685 -0
  101. data/lib/action_dispatch/middleware/debug_exceptions.rb +205 -0
  102. data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
  103. data/lib/action_dispatch/middleware/exception_wrapper.rb +147 -0
  104. data/lib/action_dispatch/middleware/executor.rb +21 -0
  105. data/lib/action_dispatch/middleware/flash.rb +300 -0
  106. data/lib/action_dispatch/middleware/public_exceptions.rb +57 -0
  107. data/lib/action_dispatch/middleware/reloader.rb +12 -0
  108. data/lib/action_dispatch/middleware/remote_ip.rb +183 -0
  109. data/lib/action_dispatch/middleware/request_id.rb +43 -0
  110. data/lib/action_dispatch/middleware/session/abstract_store.rb +92 -0
  111. data/lib/action_dispatch/middleware/session/cache_store.rb +54 -0
  112. data/lib/action_dispatch/middleware/session/cookie_store.rb +118 -0
  113. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +28 -0
  114. data/lib/action_dispatch/middleware/show_exceptions.rb +62 -0
  115. data/lib/action_dispatch/middleware/ssl.rb +150 -0
  116. data/lib/action_dispatch/middleware/stack.rb +116 -0
  117. data/lib/action_dispatch/middleware/static.rb +130 -0
  118. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +22 -0
  119. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
  120. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +27 -0
  121. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  122. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +52 -0
  123. data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
  124. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +16 -0
  125. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
  126. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +21 -0
  127. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +13 -0
  128. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +161 -0
  129. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
  130. data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +32 -0
  132. data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
  133. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +6 -0
  136. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
  137. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
  138. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +200 -0
  139. data/lib/action_dispatch/railtie.rb +55 -0
  140. data/lib/action_dispatch/request/session.rb +234 -0
  141. data/lib/action_dispatch/request/utils.rb +78 -0
  142. data/lib/action_dispatch/routing.rb +260 -0
  143. data/lib/action_dispatch/routing/endpoint.rb +17 -0
  144. data/lib/action_dispatch/routing/inspector.rb +225 -0
  145. data/lib/action_dispatch/routing/mapper.rb +2267 -0
  146. data/lib/action_dispatch/routing/polymorphic_routes.rb +352 -0
  147. data/lib/action_dispatch/routing/redirection.rb +201 -0
  148. data/lib/action_dispatch/routing/route_set.rb +890 -0
  149. data/lib/action_dispatch/routing/routes_proxy.rb +69 -0
  150. data/lib/action_dispatch/routing/url_for.rb +236 -0
  151. data/lib/action_dispatch/system_test_case.rb +147 -0
  152. data/lib/action_dispatch/system_testing/browser.rb +49 -0
  153. data/lib/action_dispatch/system_testing/driver.rb +59 -0
  154. data/lib/action_dispatch/system_testing/server.rb +31 -0
  155. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +96 -0
  156. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +31 -0
  157. data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
  158. data/lib/action_dispatch/testing/assertion_response.rb +47 -0
  159. data/lib/action_dispatch/testing/assertions.rb +24 -0
  160. data/lib/action_dispatch/testing/assertions/response.rb +107 -0
  161. data/lib/action_dispatch/testing/assertions/routing.rb +222 -0
  162. data/lib/action_dispatch/testing/integration.rb +652 -0
  163. data/lib/action_dispatch/testing/request_encoder.rb +55 -0
  164. data/lib/action_dispatch/testing/test_process.rb +50 -0
  165. data/lib/action_dispatch/testing/test_request.rb +71 -0
  166. data/lib/action_dispatch/testing/test_response.rb +53 -0
  167. data/lib/action_pack.rb +26 -0
  168. data/lib/action_pack/gem_version.rb +17 -0
  169. data/lib/action_pack/version.rb +10 -0
  170. metadata +318 -0
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/inflector/methods"
4
+ require "active_support/dependencies"
5
+
6
+ module ActionDispatch
7
+ class MiddlewareStack
8
+ class Middleware
9
+ attr_reader :args, :block, :klass
10
+
11
+ def initialize(klass, args, block)
12
+ @klass = klass
13
+ @args = args
14
+ @block = block
15
+ end
16
+
17
+ def name; klass.name; end
18
+
19
+ def ==(middleware)
20
+ case middleware
21
+ when Middleware
22
+ klass == middleware.klass
23
+ when Class
24
+ klass == middleware
25
+ end
26
+ end
27
+
28
+ def inspect
29
+ if klass.is_a?(Class)
30
+ klass.to_s
31
+ else
32
+ klass.class.to_s
33
+ end
34
+ end
35
+
36
+ def build(app)
37
+ klass.new(app, *args, &block)
38
+ end
39
+ end
40
+
41
+ include Enumerable
42
+
43
+ attr_accessor :middlewares
44
+
45
+ def initialize(*args)
46
+ @middlewares = []
47
+ yield(self) if block_given?
48
+ end
49
+
50
+ def each
51
+ @middlewares.each { |x| yield x }
52
+ end
53
+
54
+ def size
55
+ middlewares.size
56
+ end
57
+
58
+ def last
59
+ middlewares.last
60
+ end
61
+
62
+ def [](i)
63
+ middlewares[i]
64
+ end
65
+
66
+ def unshift(klass, *args, &block)
67
+ middlewares.unshift(build_middleware(klass, args, block))
68
+ end
69
+
70
+ def initialize_copy(other)
71
+ self.middlewares = other.middlewares.dup
72
+ end
73
+
74
+ def insert(index, klass, *args, &block)
75
+ index = assert_index(index, :before)
76
+ middlewares.insert(index, build_middleware(klass, args, block))
77
+ end
78
+
79
+ alias_method :insert_before, :insert
80
+
81
+ def insert_after(index, *args, &block)
82
+ index = assert_index(index, :after)
83
+ insert(index + 1, *args, &block)
84
+ end
85
+
86
+ def swap(target, *args, &block)
87
+ index = assert_index(target, :before)
88
+ insert(index, *args, &block)
89
+ middlewares.delete_at(index + 1)
90
+ end
91
+
92
+ def delete(target)
93
+ middlewares.delete_if { |m| m.klass == target }
94
+ end
95
+
96
+ def use(klass, *args, &block)
97
+ middlewares.push(build_middleware(klass, args, block))
98
+ end
99
+
100
+ def build(app = Proc.new)
101
+ middlewares.freeze.reverse.inject(app) { |a, e| e.build(a) }
102
+ end
103
+
104
+ private
105
+
106
+ def assert_index(index, where)
107
+ i = index.is_a?(Integer) ? index : middlewares.index { |m| m.klass == index }
108
+ raise "No such middleware to insert #{where}: #{index.inspect}" unless i
109
+ i
110
+ end
111
+
112
+ def build_middleware(klass, args, block)
113
+ Middleware.new(klass, args, block)
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack/utils"
4
+ require "active_support/core_ext/uri"
5
+
6
+ module ActionDispatch
7
+ # This middleware returns a file's contents from disk in the body response.
8
+ # When initialized, it can accept optional HTTP headers, which will be set
9
+ # when a response containing a file's contents is delivered.
10
+ #
11
+ # This middleware will render the file specified in <tt>env["PATH_INFO"]</tt>
12
+ # where the base path is in the +root+ directory. For example, if the +root+
13
+ # is set to +public/+, then a request with <tt>env["PATH_INFO"]</tt> of
14
+ # +assets/application.js+ will return a response with the contents of a file
15
+ # located at +public/assets/application.js+ if the file exists. If the file
16
+ # does not exist, a 404 "File not Found" response will be returned.
17
+ class FileHandler
18
+ def initialize(root, index: "index", headers: {})
19
+ @root = root.chomp("/").b
20
+ @file_server = ::Rack::File.new(@root, headers)
21
+ @index = index
22
+ end
23
+
24
+ # Takes a path to a file. If the file is found, has valid encoding, and has
25
+ # correct read permissions, the return value is a URI-escaped string
26
+ # representing the filename. Otherwise, false is returned.
27
+ #
28
+ # Used by the +Static+ class to check the existence of a valid file
29
+ # in the server's +public/+ directory (see Static#call).
30
+ def match?(path)
31
+ path = ::Rack::Utils.unescape_path path
32
+ return false unless ::Rack::Utils.valid_path? path
33
+ path = ::Rack::Utils.clean_path_info path
34
+
35
+ paths = [path, "#{path}#{ext}", "#{path}/#{@index}#{ext}"]
36
+
37
+ if match = paths.detect { |p|
38
+ path = File.join(@root, p.b)
39
+ begin
40
+ File.file?(path) && File.readable?(path)
41
+ rescue SystemCallError
42
+ false
43
+ end
44
+
45
+ }
46
+ return ::Rack::Utils.escape_path(match).b
47
+ end
48
+ end
49
+
50
+ def call(env)
51
+ serve(Rack::Request.new(env))
52
+ end
53
+
54
+ def serve(request)
55
+ path = request.path_info
56
+ gzip_path = gzip_file_path(path)
57
+
58
+ if gzip_path && gzip_encoding_accepted?(request)
59
+ request.path_info = gzip_path
60
+ status, headers, body = @file_server.call(request.env)
61
+ if status == 304
62
+ return [status, headers, body]
63
+ end
64
+ headers["Content-Encoding"] = "gzip"
65
+ headers["Content-Type"] = content_type(path)
66
+ else
67
+ status, headers, body = @file_server.call(request.env)
68
+ end
69
+
70
+ headers["Vary"] = "Accept-Encoding" if gzip_path
71
+
72
+ return [status, headers, body]
73
+ ensure
74
+ request.path_info = path
75
+ end
76
+
77
+ private
78
+ def ext
79
+ ::ActionController::Base.default_static_extension
80
+ end
81
+
82
+ def content_type(path)
83
+ ::Rack::Mime.mime_type(::File.extname(path), "text/plain".freeze)
84
+ end
85
+
86
+ def gzip_encoding_accepted?(request)
87
+ request.accept_encoding.any? { |enc, quality| enc =~ /\bgzip\b/i }
88
+ end
89
+
90
+ def gzip_file_path(path)
91
+ can_gzip_mime = content_type(path) =~ /\A(?:text\/|application\/javascript)/
92
+ gzip_path = "#{path}.gz"
93
+ if can_gzip_mime && File.exist?(File.join(@root, ::Rack::Utils.unescape_path(gzip_path).b))
94
+ gzip_path.b
95
+ else
96
+ false
97
+ end
98
+ end
99
+ end
100
+
101
+ # This middleware will attempt to return the contents of a file's body from
102
+ # disk in the response. If a file is not found on disk, the request will be
103
+ # delegated to the application stack. This middleware is commonly initialized
104
+ # to serve assets from a server's +public/+ directory.
105
+ #
106
+ # This middleware verifies the path to ensure that only files
107
+ # living in the root directory can be rendered. A request cannot
108
+ # produce a directory traversal using this middleware. Only 'GET' and 'HEAD'
109
+ # requests will result in a file being returned.
110
+ class Static
111
+ def initialize(app, path, index: "index", headers: {})
112
+ @app = app
113
+ @file_handler = FileHandler.new(path, index: index, headers: headers)
114
+ end
115
+
116
+ def call(env)
117
+ req = Rack::Request.new env
118
+
119
+ if req.get? || req.head?
120
+ path = req.path_info.chomp("/".freeze)
121
+ if match = @file_handler.match?(path)
122
+ req.path_info = match
123
+ return @file_handler.serve(req)
124
+ end
125
+ end
126
+
127
+ @app.call(req.env)
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,22 @@
1
+ <% unless @exception.blamed_files.blank? %>
2
+ <% if (hide = @exception.blamed_files.length > 8) %>
3
+ <a href="#" onclick="return toggleTrace()">Toggle blamed files</a>
4
+ <% end %>
5
+ <pre id="blame_trace" <%='style="display:none"' if hide %>><code><%= @exception.describe_blame %></code></pre>
6
+ <% end %>
7
+
8
+ <h2 style="margin-top: 30px">Request</h2>
9
+ <p><b>Parameters</b>:</p> <pre><%= debug_params(@request.filtered_parameters) %></pre>
10
+
11
+ <div class="details">
12
+ <div class="summary"><a href="#" onclick="return toggleSessionDump()">Toggle session dump</a></div>
13
+ <div id="session_dump" style="display:none"><pre><%= debug_hash @request.session %></pre></div>
14
+ </div>
15
+
16
+ <div class="details">
17
+ <div class="summary"><a href="#" onclick="return toggleEnvDump()">Toggle env dump</a></div>
18
+ <div id="env_dump" style="display:none"><pre><%= debug_hash @request.env.slice(*@request.class::ENV_METHODS) %></pre></div>
19
+ </div>
20
+
21
+ <h2 style="margin-top: 30px">Response</h2>
22
+ <p><b>Headers</b>:</p> <pre><%= debug_headers(defined?(@response) ? @response.headers : {}) %></pre>
@@ -0,0 +1,23 @@
1
+ <%
2
+ clean_params = @request.filtered_parameters.clone
3
+ clean_params.delete("action")
4
+ clean_params.delete("controller")
5
+
6
+ request_dump = clean_params.empty? ? 'None' : clean_params.inspect.gsub(',', ",\n")
7
+
8
+ def debug_hash(object)
9
+ object.to_hash.sort_by { |k, _| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n")
10
+ end unless self.class.method_defined?(:debug_hash)
11
+ %>
12
+
13
+ Request parameters
14
+ <%= request_dump %>
15
+
16
+ Session dump
17
+ <%= debug_hash @request.session %>
18
+
19
+ Env dump
20
+ <%= debug_hash @request.env.slice(*@request.class::ENV_METHODS) %>
21
+
22
+ Response headers
23
+ <%= defined?(@response) ? @response.headers.inspect.gsub(',', ",\n") : 'None' %>
@@ -0,0 +1,27 @@
1
+ <% @source_extracts.each_with_index do |source_extract, index| %>
2
+ <% if source_extract[:code] %>
3
+ <div class="source <%="hidden" if @show_source_idx != index%>" id="frame-source-<%=index%>">
4
+ <div class="info">
5
+ Extracted source (around line <strong>#<%= source_extract[:line_number] %></strong>):
6
+ </div>
7
+ <div class="data">
8
+ <table cellpadding="0" cellspacing="0" class="lines">
9
+ <tr>
10
+ <td>
11
+ <pre class="line_numbers">
12
+ <% source_extract[:code].each_key do |line_number| %>
13
+ <span><%= line_number -%></span>
14
+ <% end %>
15
+ </pre>
16
+ </td>
17
+ <td width="100%">
18
+ <pre>
19
+ <% source_extract[:code].each do |line, source| -%><div class="line<%= " active" if line == source_extract[:line_number] -%>"><%= source -%></div><% end -%>
20
+ </pre>
21
+ </td>
22
+ </tr>
23
+ </table>
24
+ </div>
25
+ </div>
26
+ <% end %>
27
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <% @source_extracts.first(3).each do |source_extract| %>
2
+ <% if source_extract[:code] %>
3
+ Extracted source (around line #<%= source_extract[:line_number] %>):
4
+
5
+ <% source_extract[:code].each do |line, source| -%>
6
+ <%= line == source_extract[:line_number] ? "*#{line}" : "##{line}" -%> <%= source -%><% end -%>
7
+ <% end %>
8
+ <% end %>
@@ -0,0 +1,52 @@
1
+ <% names = @traces.keys %>
2
+
3
+ <p><code>Rails.root: <%= defined?(Rails) && Rails.respond_to?(:root) ? Rails.root : "unset" %></code></p>
4
+
5
+ <div id="traces">
6
+ <% names.each do |name| %>
7
+ <%
8
+ show = "show('#{name.gsub(/\s/, '-')}');"
9
+ hide = (names - [name]).collect {|hide_name| "hide('#{hide_name.gsub(/\s/, '-')}');"}
10
+ %>
11
+ <a href="#" onclick="<%= hide.join %><%= show %>; return false;"><%= name %></a> <%= '|' unless names.last == name %>
12
+ <% end %>
13
+
14
+ <% @traces.each do |name, trace| %>
15
+ <div id="<%= name.gsub(/\s/, '-') %>" style="display: <%= (name == @trace_to_show) ? 'block' : 'none' %>;">
16
+ <pre><code><% trace.each do |frame| %><a class="trace-frames" data-frame-id="<%= frame[:id] %>" href="#"><%= frame[:trace] %></a><br><% end %></code></pre>
17
+ </div>
18
+ <% end %>
19
+
20
+ <script type="text/javascript">
21
+ var traceFrames = document.getElementsByClassName('trace-frames');
22
+ var selectedFrame, currentSource = document.getElementById('frame-source-0');
23
+
24
+ // Add click listeners for all stack frames
25
+ for (var i = 0; i < traceFrames.length; i++) {
26
+ traceFrames[i].addEventListener('click', function(e) {
27
+ e.preventDefault();
28
+ var target = e.target;
29
+ var frame_id = target.dataset.frameId;
30
+
31
+ if (selectedFrame) {
32
+ selectedFrame.className = selectedFrame.className.replace("selected", "");
33
+ }
34
+
35
+ target.className += " selected";
36
+ selectedFrame = target;
37
+
38
+ // Change the extracted source code
39
+ changeSourceExtract(frame_id);
40
+ });
41
+
42
+ function changeSourceExtract(frame_id) {
43
+ var el = document.getElementById('frame-source-' + frame_id);
44
+ if (currentSource && el) {
45
+ currentSource.className += " hidden";
46
+ el.className = el.className.replace(" hidden", "");
47
+ currentSource = el;
48
+ }
49
+ }
50
+ }
51
+ </script>
52
+ </div>
@@ -0,0 +1,9 @@
1
+ Rails.root: <%= defined?(Rails) && Rails.respond_to?(:root) ? Rails.root : "unset" %>
2
+
3
+ <% @traces.each do |name, trace| %>
4
+ <% if trace.any? %>
5
+ <%= name %>
6
+ <%= trace.map { |t| t[:trace] }.join("\n") %>
7
+
8
+ <% end %>
9
+ <% end %>
@@ -0,0 +1,16 @@
1
+ <header>
2
+ <h1>
3
+ <%= @exception.class.to_s %>
4
+ <% if @request.parameters['controller'] %>
5
+ in <%= @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%= @request.parameters['action'] %><% end %>
6
+ <% end %>
7
+ </h1>
8
+ </header>
9
+
10
+ <div id="container">
11
+ <h2><%= h @exception.message %></h2>
12
+
13
+ <%= render template: "rescues/_source" %>
14
+ <%= render template: "rescues/_trace" %>
15
+ <%= render template: "rescues/_request_and_response" %>
16
+ </div>
@@ -0,0 +1,9 @@
1
+ <%= @exception.class.to_s %><%
2
+ if @request.parameters['controller']
3
+ %> in <%= @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%= @request.parameters['action'] %><% end %>
4
+ <% end %>
5
+
6
+ <%= @exception.message %>
7
+ <%= render template: "rescues/_source" %>
8
+ <%= render template: "rescues/_trace" %>
9
+ <%= render template: "rescues/_request_and_response" %>
@@ -0,0 +1,21 @@
1
+ <header>
2
+ <h1>
3
+ <%= @exception.class.to_s %>
4
+ <% if @request.parameters['controller'] %>
5
+ in <%= @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%= @request.parameters['action'] %><% end %>
6
+ <% end %>
7
+ </h1>
8
+ </header>
9
+
10
+ <div id="container">
11
+ <h2>
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
15
+ <% end %>
16
+ </h2>
17
+
18
+ <%= render template: "rescues/_source" %>
19
+ <%= render template: "rescues/_trace" %>
20
+ <%= render template: "rescues/_request_and_response" %>
21
+ </div>