actionpack 6.0.0.beta1 → 6.0.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +125 -13
- data/README.rdoc +2 -1
- data/lib/abstract_controller/caching/fragments.rb +0 -1
- data/lib/abstract_controller/translation.rb +1 -0
- data/lib/action_controller.rb +4 -1
- data/lib/action_controller/metal.rb +3 -3
- data/lib/action_controller/metal/basic_implicit_render.rb +1 -1
- data/lib/action_controller/metal/etag_with_template_digest.rb +1 -1
- data/lib/action_controller/metal/exceptions.rb +2 -2
- data/lib/action_controller/metal/force_ssl.rb +1 -2
- data/lib/action_controller/metal/helpers.rb +2 -2
- data/lib/action_controller/metal/implicit_render.rb +2 -2
- data/lib/action_controller/metal/live.rb +2 -2
- data/lib/action_controller/metal/mime_responds.rb +1 -1
- data/lib/action_controller/metal/params_wrapper.rb +2 -2
- data/lib/action_controller/metal/redirecting.rb +6 -27
- data/lib/action_controller/metal/renderers.rb +4 -4
- data/lib/action_controller/metal/rendering.rb +1 -1
- data/lib/action_controller/metal/request_forgery_protection.rb +2 -2
- data/lib/action_controller/metal/strong_parameters.rb +6 -12
- data/lib/action_controller/renderer.rb +2 -2
- data/lib/action_controller/template_assertions.rb +1 -1
- data/lib/action_controller/test_case.rb +3 -2
- data/lib/action_dispatch.rb +1 -1
- data/lib/action_dispatch/http/content_security_policy.rb +20 -9
- data/lib/action_dispatch/http/mime_negotiation.rb +5 -0
- data/lib/action_dispatch/http/mime_type.rb +13 -1
- data/lib/action_dispatch/http/response.rb +27 -7
- data/lib/action_dispatch/http/upload.rb +4 -1
- data/lib/action_dispatch/journey/formatter.rb +1 -1
- data/lib/action_dispatch/journey/path/pattern.rb +6 -1
- data/lib/action_dispatch/journey/route.rb +5 -4
- data/lib/action_dispatch/journey/routes.rb +0 -1
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +39 -0
- data/lib/action_dispatch/middleware/cookies.rb +9 -10
- data/lib/action_dispatch/middleware/debug_exceptions.rb +8 -2
- data/lib/action_dispatch/middleware/debug_view.rb +19 -1
- data/lib/action_dispatch/middleware/exception_wrapper.rb +15 -10
- data/lib/action_dispatch/middleware/host_authorization.rb +2 -2
- data/lib/action_dispatch/middleware/public_exceptions.rb +6 -2
- data/lib/action_dispatch/middleware/remote_ip.rb +3 -3
- data/lib/action_dispatch/middleware/session/cookie_store.rb +4 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +1 -1
- data/lib/action_dispatch/middleware/stack.rb +34 -2
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +3 -1
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +6 -2
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +4 -1
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +3 -1
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +4 -0
- data/lib/action_dispatch/railtie.rb +6 -2
- data/lib/action_dispatch/routing.rb +18 -18
- data/lib/action_dispatch/routing/mapper.rb +26 -11
- data/lib/action_dispatch/routing/route_set.rb +13 -15
- data/lib/action_dispatch/system_test_case.rb +43 -5
- data/lib/action_dispatch/system_testing/browser.rb +38 -7
- data/lib/action_dispatch/system_testing/driver.rb +10 -1
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +3 -2
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +7 -6
- data/lib/action_dispatch/testing/assertions.rb +1 -1
- data/lib/action_dispatch/testing/assertions/routing.rb +8 -1
- data/lib/action_dispatch/testing/integration.rb +2 -2
- data/lib/action_dispatch/testing/request_encoder.rb +2 -2
- data/lib/action_dispatch/testing/test_response.rb +1 -1
- data/lib/action_pack/gem_version.rb +2 -2
- metadata +20 -15
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +0 -26
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "erb"
|
4
|
+
require "action_dispatch/http/request"
|
5
|
+
require "active_support/actionable_error"
|
6
|
+
|
7
|
+
module ActionDispatch
|
8
|
+
class ActionableExceptions # :nodoc:
|
9
|
+
cattr_accessor :endpoint, default: "/rails/actions"
|
10
|
+
|
11
|
+
def initialize(app)
|
12
|
+
@app = app
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
request = ActionDispatch::Request.new(env)
|
17
|
+
return @app.call(env) unless actionable_request?(request)
|
18
|
+
|
19
|
+
ActiveSupport::ActionableError.dispatch(request.params[:error].to_s.safe_constantize, request.params[:action])
|
20
|
+
|
21
|
+
redirect_to request.params[:location]
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def actionable_request?(request)
|
26
|
+
request.show_exceptions? && request.post? && request.path == endpoint
|
27
|
+
end
|
28
|
+
|
29
|
+
def redirect_to(location)
|
30
|
+
body = "<html><body>You are being <a href=\"#{ERB::Util.unwrapped_html_escape(location)}\">redirected</a>.</body></html>"
|
31
|
+
|
32
|
+
[302, {
|
33
|
+
"Content-Type" => "text/html; charset=#{Response.default_charset}",
|
34
|
+
"Content-Length" => body.bytesize.to_s,
|
35
|
+
"Location" => location,
|
36
|
+
}, [body]]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -338,7 +338,7 @@ module ActionDispatch
|
|
338
338
|
|
339
339
|
def update_cookies_from_jar
|
340
340
|
request_jar = @request.cookie_jar.instance_variable_get(:@cookies)
|
341
|
-
set_cookies = request_jar.reject { |k, _| @delete_cookies.key?(k) }
|
341
|
+
set_cookies = request_jar.reject { |k, _| @delete_cookies.key?(k) || @set_cookies.key?(k) }
|
342
342
|
|
343
343
|
@cookies.update set_cookies if set_cookies
|
344
344
|
end
|
@@ -488,13 +488,8 @@ module ActionDispatch
|
|
488
488
|
end
|
489
489
|
|
490
490
|
def cookie_metadata(name, options)
|
491
|
-
|
492
|
-
metadata =
|
493
|
-
metadata[:purpose] = "cookie.#{name}"
|
494
|
-
|
495
|
-
metadata
|
496
|
-
else
|
497
|
-
{}
|
491
|
+
expiry_options(options).tap do |metadata|
|
492
|
+
metadata[:purpose] = "cookie.#{name}" if request.use_cookies_with_metadata
|
498
493
|
end
|
499
494
|
end
|
500
495
|
|
@@ -539,9 +534,13 @@ module ActionDispatch
|
|
539
534
|
if value
|
540
535
|
case
|
541
536
|
when needs_migration?(value)
|
542
|
-
|
537
|
+
Marshal.load(value).tap do |v|
|
538
|
+
self[name] = { value: v }
|
539
|
+
end
|
543
540
|
when rotate
|
544
|
-
|
541
|
+
serializer.load(value).tap do |v|
|
542
|
+
self[name] = { value: v }
|
543
|
+
end
|
545
544
|
else
|
546
545
|
serializer.load(value)
|
547
546
|
end
|
@@ -4,6 +4,8 @@ require "action_dispatch/http/request"
|
|
4
4
|
require "action_dispatch/middleware/exception_wrapper"
|
5
5
|
require "action_dispatch/routing/inspector"
|
6
6
|
|
7
|
+
require "active_support/actionable_error"
|
8
|
+
|
7
9
|
require "action_view"
|
8
10
|
require "action_view/base"
|
9
11
|
|
@@ -60,7 +62,11 @@ module ActionDispatch
|
|
60
62
|
log_error(request, wrapper)
|
61
63
|
|
62
64
|
if request.get_header("action_dispatch.show_detailed_exceptions")
|
63
|
-
|
65
|
+
begin
|
66
|
+
content_type = request.formats.first
|
67
|
+
rescue Mime::Type::InvalidMimeType
|
68
|
+
render_for_api_request(Mime[:text], wrapper)
|
69
|
+
end
|
64
70
|
|
65
71
|
if api_request?(content_type)
|
66
72
|
render_for_api_request(content_type, wrapper)
|
@@ -142,7 +148,7 @@ module ActionDispatch
|
|
142
148
|
message = []
|
143
149
|
message << " "
|
144
150
|
message << "#{exception.class} (#{exception.message}):"
|
145
|
-
message.concat(exception.
|
151
|
+
message.concat(exception.annotated_source_code) if exception.respond_to?(:annotated_source_code)
|
146
152
|
message << " "
|
147
153
|
message.concat(trace)
|
148
154
|
|
@@ -10,7 +10,13 @@ module ActionDispatch
|
|
10
10
|
RESCUES_TEMPLATE_PATH = File.expand_path("templates", __dir__)
|
11
11
|
|
12
12
|
def initialize(assigns)
|
13
|
-
|
13
|
+
paths = [RESCUES_TEMPLATE_PATH]
|
14
|
+
lookup_context = ActionView::LookupContext.new(paths)
|
15
|
+
super(lookup_context, assigns)
|
16
|
+
end
|
17
|
+
|
18
|
+
def compiled_method_container
|
19
|
+
self.class
|
14
20
|
end
|
15
21
|
|
16
22
|
def debug_params(params)
|
@@ -46,5 +52,17 @@ module ActionDispatch
|
|
46
52
|
super
|
47
53
|
end
|
48
54
|
end
|
55
|
+
|
56
|
+
def protect_against_forgery?
|
57
|
+
false
|
58
|
+
end
|
59
|
+
|
60
|
+
def params_valid?
|
61
|
+
begin
|
62
|
+
@request.parameters
|
63
|
+
rescue ActionController::BadRequest
|
64
|
+
false
|
65
|
+
end
|
66
|
+
end
|
49
67
|
end
|
50
68
|
end
|
@@ -12,6 +12,7 @@ module ActionDispatch
|
|
12
12
|
"ActionController::UnknownHttpMethod" => :method_not_allowed,
|
13
13
|
"ActionController::NotImplemented" => :not_implemented,
|
14
14
|
"ActionController::UnknownFormat" => :not_acceptable,
|
15
|
+
"Mime::Type::InvalidMimeType" => :not_acceptable,
|
15
16
|
"ActionController::MissingExactTemplate" => :not_acceptable,
|
16
17
|
"ActionController::InvalidAuthenticityToken" => :unprocessable_entity,
|
17
18
|
"ActionController::InvalidCrossOriginRequest" => :unprocessable_entity,
|
@@ -31,22 +32,34 @@ module ActionDispatch
|
|
31
32
|
"ActionController::MissingExactTemplate" => "missing_exact_template",
|
32
33
|
)
|
33
34
|
|
35
|
+
cattr_accessor :wrapper_exceptions, default: [
|
36
|
+
"ActionView::Template::Error"
|
37
|
+
]
|
38
|
+
|
34
39
|
attr_reader :backtrace_cleaner, :exception, :wrapped_causes, :line_number, :file
|
35
40
|
|
36
41
|
def initialize(backtrace_cleaner, exception)
|
37
42
|
@backtrace_cleaner = backtrace_cleaner
|
38
|
-
@exception =
|
43
|
+
@exception = exception
|
39
44
|
@wrapped_causes = wrapped_causes_for(exception, backtrace_cleaner)
|
40
45
|
|
41
46
|
expand_backtrace if exception.is_a?(SyntaxError) || exception.cause.is_a?(SyntaxError)
|
42
47
|
end
|
43
48
|
|
49
|
+
def unwrapped_exception
|
50
|
+
if wrapper_exceptions.include?(exception.class.to_s)
|
51
|
+
exception.cause
|
52
|
+
else
|
53
|
+
exception
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
44
57
|
def rescue_template
|
45
58
|
@@rescue_templates[@exception.class.name]
|
46
59
|
end
|
47
60
|
|
48
61
|
def status_code
|
49
|
-
self.class.status_code_for_exception(
|
62
|
+
self.class.status_code_for_exception(unwrapped_exception.class.name)
|
50
63
|
end
|
51
64
|
|
52
65
|
def application_trace
|
@@ -122,14 +135,6 @@ module ActionDispatch
|
|
122
135
|
Array(@exception.backtrace)
|
123
136
|
end
|
124
137
|
|
125
|
-
def original_exception(exception)
|
126
|
-
if @@rescue_responses.has_key?(exception.cause.class.name)
|
127
|
-
exception.cause
|
128
|
-
else
|
129
|
-
exception
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
138
|
def causes_for(exception)
|
134
139
|
return enum_for(__method__, exception) unless block_given?
|
135
140
|
|
@@ -3,8 +3,8 @@
|
|
3
3
|
require "action_dispatch/http/request"
|
4
4
|
|
5
5
|
module ActionDispatch
|
6
|
-
# This middleware guards from DNS rebinding attacks by
|
7
|
-
# hosts a request can be sent to.
|
6
|
+
# This middleware guards from DNS rebinding attacks by explicitly permitting
|
7
|
+
# the hosts a request can be sent to.
|
8
8
|
#
|
9
9
|
# When a request comes to an unauthorized host, the +response_app+
|
10
10
|
# application will be executed and rendered. If no +response_app+ is given, a
|
@@ -21,8 +21,12 @@ module ActionDispatch
|
|
21
21
|
def call(env)
|
22
22
|
request = ActionDispatch::Request.new(env)
|
23
23
|
status = request.path_info[1..-1].to_i
|
24
|
-
|
25
|
-
|
24
|
+
begin
|
25
|
+
content_type = request.formats.first
|
26
|
+
rescue Mime::Type::InvalidMimeType
|
27
|
+
content_type = Mime[:text]
|
28
|
+
end
|
29
|
+
body = { status: status, error: Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500]) }
|
26
30
|
|
27
31
|
render(status, content_type, body)
|
28
32
|
end
|
@@ -8,13 +8,13 @@ module ActionDispatch
|
|
8
8
|
# contain the address, and then picking the last-set address that is not
|
9
9
|
# on the list of trusted IPs. This follows the precedent set by e.g.
|
10
10
|
# {the Tomcat server}[https://issues.apache.org/bugzilla/show_bug.cgi?id=50453],
|
11
|
-
# with {reasoning explained at length}[
|
11
|
+
# with {reasoning explained at length}[https://blog.gingerlime.com/2012/rails-ip-spoofing-vulnerabilities-and-protection]
|
12
12
|
# by @gingerlime. A more detailed explanation of the algorithm is given
|
13
13
|
# at GetIp#calculate_ip.
|
14
14
|
#
|
15
15
|
# Some Rack servers concatenate repeated headers, like {HTTP RFC 2616}[https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2]
|
16
16
|
# requires. Some Rack servers simply drop preceding headers, and only report
|
17
|
-
# the value that was {given in the last header}[
|
17
|
+
# the value that was {given in the last header}[https://andre.arko.net/2011/12/26/repeated-headers-and-ruby-web-servers].
|
18
18
|
# If you are behind multiple proxy servers (like NGINX to HAProxy to Unicorn)
|
19
19
|
# then you should test your Rack server to make sure your data is good.
|
20
20
|
#
|
@@ -102,7 +102,7 @@ module ActionDispatch
|
|
102
102
|
# proxies, that header may contain a list of IPs. Other proxy services
|
103
103
|
# set the Client-Ip header instead, so we check that too.
|
104
104
|
#
|
105
|
-
# As discussed in {this post about Rails IP Spoofing}[
|
105
|
+
# As discussed in {this post about Rails IP Spoofing}[https://blog.gingerlime.com/2012/rails-ip-spoofing-vulnerabilities-and-protection/],
|
106
106
|
# while the first IP in the list is likely to be the "originating" IP,
|
107
107
|
# it could also have been set by the client maliciously.
|
108
108
|
#
|
@@ -24,9 +24,10 @@ module ActionDispatch
|
|
24
24
|
#
|
25
25
|
# Rails.application.config.session_store :cookie_store, key: '_your_app_session'
|
26
26
|
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
# encrypted in the
|
27
|
+
# In the development and test environments your application's secret key base is
|
28
|
+
# generated by Rails and stored in a temporary file in <tt>tmp/development_secret.txt</tt>.
|
29
|
+
# In all other environments, it is stored encrypted in the
|
30
|
+
# <tt>config/credentials.yml.enc</tt> file.
|
30
31
|
#
|
31
32
|
# If your application was not updated to Rails 5.2 defaults, the secret_key_base
|
32
33
|
# will be found in the old <tt>config/secrets.yml</tt> file.
|
@@ -45,7 +45,7 @@ module ActionDispatch
|
|
45
45
|
backtrace_cleaner = request.get_header "action_dispatch.backtrace_cleaner"
|
46
46
|
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
|
47
47
|
status = wrapper.status_code
|
48
|
-
request.set_header "action_dispatch.exception", wrapper.
|
48
|
+
request.set_header "action_dispatch.exception", wrapper.unwrapped_exception
|
49
49
|
request.set_header "action_dispatch.original_path", request.path_info
|
50
50
|
request.path_info = "/#{status}"
|
51
51
|
response = @exceptions_app.call(request.env)
|
@@ -36,6 +36,31 @@ module ActionDispatch
|
|
36
36
|
def build(app)
|
37
37
|
klass.new(app, *args, &block)
|
38
38
|
end
|
39
|
+
|
40
|
+
def build_instrumented(app)
|
41
|
+
InstrumentationProxy.new(build(app), inspect)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# This class is used to instrument the execution of a single middleware.
|
46
|
+
# It proxies the `call` method transparently and instruments the method
|
47
|
+
# call.
|
48
|
+
class InstrumentationProxy
|
49
|
+
EVENT_NAME = "process_middleware.action_dispatch"
|
50
|
+
|
51
|
+
def initialize(middleware, class_name)
|
52
|
+
@middleware = middleware
|
53
|
+
|
54
|
+
@payload = {
|
55
|
+
middleware: class_name,
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
def call(env)
|
60
|
+
ActiveSupport::Notifications.instrument(EVENT_NAME, @payload) do
|
61
|
+
@middleware.call(env)
|
62
|
+
end
|
63
|
+
end
|
39
64
|
end
|
40
65
|
|
41
66
|
include Enumerable
|
@@ -97,8 +122,15 @@ module ActionDispatch
|
|
97
122
|
middlewares.push(build_middleware(klass, args, block))
|
98
123
|
end
|
99
124
|
|
100
|
-
def build(app =
|
101
|
-
|
125
|
+
def build(app = nil, &block)
|
126
|
+
instrumenting = ActiveSupport::Notifications.notifier.listening?(InstrumentationProxy::EVENT_NAME)
|
127
|
+
middlewares.freeze.reverse.inject(app || block) do |a, e|
|
128
|
+
if instrumenting
|
129
|
+
e.build_instrumented(a)
|
130
|
+
else
|
131
|
+
e.build(a)
|
132
|
+
end
|
133
|
+
end
|
102
134
|
end
|
103
135
|
|
104
136
|
private
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<% actions = ActiveSupport::ActionableError.actions(exception) %>
|
2
|
+
|
3
|
+
<% if actions.any? %>
|
4
|
+
<div class="actions">
|
5
|
+
<% actions.each do |action, _| %>
|
6
|
+
<%= button_to action, ActionDispatch::ActionableExceptions.endpoint, params: {
|
7
|
+
error: exception.class.name,
|
8
|
+
action: action,
|
9
|
+
location: request.path
|
10
|
+
} %>
|
11
|
+
<% end %>
|
12
|
+
</div>
|
13
|
+
<% end %>
|
File without changes
|
@@ -6,7 +6,9 @@
|
|
6
6
|
<% end %>
|
7
7
|
|
8
8
|
<h2 style="margin-top: 30px">Request</h2>
|
9
|
-
|
9
|
+
<% if params_valid? %>
|
10
|
+
<p><b>Parameters</b>:</p> <pre><%= debug_params(@request.filtered_parameters) %></pre>
|
11
|
+
<% end %>
|
10
12
|
|
11
13
|
<div class="details">
|
12
14
|
<div class="summary"><a href="#" onclick="return toggleSessionDump()">Toggle session dump</a></div>
|
@@ -2,6 +2,6 @@
|
|
2
2
|
<h1>Blocked host: <%= @host %></h1>
|
3
3
|
</header>
|
4
4
|
<div id="container">
|
5
|
-
<h2>To allow requests to <%= @host %>, add the following configuration:</h2>
|
6
|
-
<pre>
|
5
|
+
<h2>To allow requests to <%= @host %>, add the following to your environment configuration:</h2>
|
6
|
+
<pre>config.hosts << "<%= @host %>"</pre>
|
7
7
|
</div>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
Blocked host: <%= @host %>
|
2
2
|
|
3
|
-
To allow requests to <%= @host %>, add the following configuration:
|
3
|
+
To allow requests to <%= @host %>, add the following to your environment configuration:
|
4
4
|
|
5
|
-
|
5
|
+
config.hosts << "<%= @host %>"
|
@@ -1,14 +1,18 @@
|
|
1
1
|
<header>
|
2
2
|
<h1>
|
3
3
|
<%= @exception.class.to_s %>
|
4
|
-
<% if @request.parameters['controller'] %>
|
4
|
+
<% if params_valid? && @request.parameters['controller'] %>
|
5
5
|
in <%= @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%= @request.parameters['action'] %><% end %>
|
6
6
|
<% end %>
|
7
7
|
</h1>
|
8
8
|
</header>
|
9
9
|
|
10
10
|
<div id="container">
|
11
|
-
<h2
|
11
|
+
<h2>
|
12
|
+
<%= h @exception.message %>
|
13
|
+
|
14
|
+
<%= render "rescues/actions", exception: @exception, request: @request %>
|
15
|
+
</h2>
|
12
16
|
|
13
17
|
<%= render "rescues/source", source_extracts: @source_extracts, show_source_idx: @show_source_idx, error_index: 0 %>
|
14
18
|
<%= render "rescues/trace", traces: @traces, trace_to_show: @trace_to_show, error_index: 0 %>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<%= @exception.class.to_s %><%
|
2
|
-
if @request.parameters['controller']
|
2
|
+
if params_valid? && @request.parameters['controller']
|
3
3
|
%> in <%= @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%= @request.parameters['action'] %><% end %>
|
4
4
|
<% end %>
|
5
5
|
|
@@ -10,9 +10,12 @@
|
|
10
10
|
<div id="container">
|
11
11
|
<h2>
|
12
12
|
<%= h @exception.message %>
|
13
|
-
<% if @exception.message.match?
|
13
|
+
<% if defined?(ActiveStorage) && @exception.message.match?(%r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}) %>
|
14
14
|
<br />To resolve this issue run: rails active_storage:install
|
15
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
|
18
|
+
<% end %>
|
16
19
|
</h2>
|
17
20
|
|
18
21
|
<%= render "rescues/source", source_extracts: @source_extracts, show_source_idx: @show_source_idx %>
|
@@ -4,8 +4,10 @@
|
|
4
4
|
<% end %>
|
5
5
|
|
6
6
|
<%= @exception.message %>
|
7
|
-
<% if @exception.message.match?
|
7
|
+
<% if defined?(ActiveStorage) && @exception.message.match?(%r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}) %>
|
8
8
|
To resolve this issue run: rails active_storage:install
|
9
|
+
<% if defined?(ActionMailbox) && @exception.message.match?(%r{#{ActionMailbox::InboundEmail.table_name}}) %>
|
10
|
+
To resolve this issue run: rails action_mailbox:install
|
9
11
|
<% end %>
|
10
12
|
|
11
13
|
<%= render template: "rescues/_source" %>
|