actionpack 7.0.8.1 → 7.1.3.4
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 +365 -353
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -2
- data/lib/abstract_controller/base.rb +20 -11
- data/lib/abstract_controller/caching/fragments.rb +2 -0
- data/lib/abstract_controller/callbacks.rb +31 -6
- data/lib/abstract_controller/deprecator.rb +7 -0
- data/lib/abstract_controller/helpers.rb +61 -18
- data/lib/abstract_controller/railties/routes_helpers.rb +1 -16
- data/lib/abstract_controller/rendering.rb +3 -3
- data/lib/abstract_controller/translation.rb +1 -20
- data/lib/abstract_controller/url_for.rb +2 -0
- data/lib/abstract_controller.rb +6 -0
- data/lib/action_controller/api.rb +5 -3
- data/lib/action_controller/base.rb +3 -17
- data/lib/action_controller/caching.rb +2 -0
- data/lib/action_controller/deprecator.rb +7 -0
- data/lib/action_controller/form_builder.rb +2 -0
- data/lib/action_controller/log_subscriber.rb +16 -4
- data/lib/action_controller/metal/content_security_policy.rb +1 -1
- data/lib/action_controller/metal/data_streaming.rb +2 -0
- data/lib/action_controller/metal/default_headers.rb +2 -0
- data/lib/action_controller/metal/etag_with_flash.rb +2 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +2 -0
- data/lib/action_controller/metal/exceptions.rb +8 -0
- data/lib/action_controller/metal/head.rb +8 -6
- data/lib/action_controller/metal/helpers.rb +3 -14
- data/lib/action_controller/metal/http_authentication.rb +17 -8
- data/lib/action_controller/metal/implicit_render.rb +5 -3
- data/lib/action_controller/metal/instrumentation.rb +8 -1
- data/lib/action_controller/metal/live.rb +24 -0
- data/lib/action_controller/metal/mime_responds.rb +2 -2
- data/lib/action_controller/metal/params_wrapper.rb +4 -2
- data/lib/action_controller/metal/permissions_policy.rb +1 -1
- data/lib/action_controller/metal/redirecting.rb +7 -7
- data/lib/action_controller/metal/renderers.rb +2 -2
- data/lib/action_controller/metal/rendering.rb +0 -7
- data/lib/action_controller/metal/request_forgery_protection.rb +139 -50
- data/lib/action_controller/metal/rescue.rb +2 -0
- data/lib/action_controller/metal/streaming.rb +70 -30
- data/lib/action_controller/metal/strong_parameters.rb +132 -52
- data/lib/action_controller/metal/url_for.rb +7 -0
- data/lib/action_controller/metal.rb +79 -21
- data/lib/action_controller/railtie.rb +22 -9
- data/lib/action_controller/renderer.rb +98 -65
- data/lib/action_controller/test_case.rb +15 -5
- data/lib/action_controller.rb +8 -1
- data/lib/action_dispatch/constants.rb +32 -0
- data/lib/action_dispatch/deprecator.rb +7 -0
- data/lib/action_dispatch/http/cache.rb +1 -3
- data/lib/action_dispatch/http/content_security_policy.rb +9 -8
- data/lib/action_dispatch/http/filter_parameters.rb +11 -5
- data/lib/action_dispatch/http/headers.rb +2 -0
- data/lib/action_dispatch/http/mime_negotiation.rb +22 -22
- data/lib/action_dispatch/http/mime_type.rb +35 -12
- data/lib/action_dispatch/http/mime_types.rb +3 -1
- data/lib/action_dispatch/http/parameters.rb +1 -1
- data/lib/action_dispatch/http/permissions_policy.rb +38 -23
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +48 -14
- data/lib/action_dispatch/http/response.rb +80 -59
- data/lib/action_dispatch/http/upload.rb +2 -0
- data/lib/action_dispatch/journey/formatter.rb +8 -2
- data/lib/action_dispatch/journey/path/pattern.rb +14 -14
- data/lib/action_dispatch/journey/route.rb +3 -2
- data/lib/action_dispatch/journey/router.rb +9 -8
- data/lib/action_dispatch/journey/routes.rb +2 -2
- data/lib/action_dispatch/log_subscriber.rb +23 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +5 -6
- data/lib/action_dispatch/middleware/assume_ssl.rb +24 -0
- data/lib/action_dispatch/middleware/callbacks.rb +2 -0
- data/lib/action_dispatch/middleware/cookies.rb +81 -98
- data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -25
- data/lib/action_dispatch/middleware/debug_locks.rb +4 -1
- data/lib/action_dispatch/middleware/debug_view.rb +7 -2
- data/lib/action_dispatch/middleware/exception_wrapper.rb +186 -27
- data/lib/action_dispatch/middleware/executor.rb +1 -1
- data/lib/action_dispatch/middleware/flash.rb +7 -0
- data/lib/action_dispatch/middleware/host_authorization.rb +6 -3
- data/lib/action_dispatch/middleware/public_exceptions.rb +5 -3
- data/lib/action_dispatch/middleware/reloader.rb +7 -5
- data/lib/action_dispatch/middleware/remote_ip.rb +17 -16
- data/lib/action_dispatch/middleware/request_id.rb +2 -0
- data/lib/action_dispatch/middleware/server_timing.rb +4 -4
- data/lib/action_dispatch/middleware/session/abstract_store.rb +5 -0
- data/lib/action_dispatch/middleware/session/cache_store.rb +2 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +11 -5
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +3 -1
- data/lib/action_dispatch/middleware/show_exceptions.rb +19 -15
- data/lib/action_dispatch/middleware/ssl.rb +18 -6
- data/lib/action_dispatch/middleware/stack.rb +7 -2
- data/lib/action_dispatch/middleware/static.rb +12 -8
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +8 -1
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +7 -7
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +17 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +16 -12
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +3 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +46 -37
- data/lib/action_dispatch/railtie.rb +14 -4
- data/lib/action_dispatch/request/session.rb +16 -6
- data/lib/action_dispatch/request/utils.rb +8 -3
- data/lib/action_dispatch/routing/inspector.rb +54 -6
- data/lib/action_dispatch/routing/mapper.rb +35 -24
- data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
- data/lib/action_dispatch/routing/redirection.rb +15 -6
- data/lib/action_dispatch/routing/route_set.rb +52 -22
- data/lib/action_dispatch/routing/routes_proxy.rb +10 -15
- data/lib/action_dispatch/routing/url_for.rb +5 -1
- data/lib/action_dispatch/routing.rb +7 -7
- data/lib/action_dispatch/system_test_case.rb +3 -3
- data/lib/action_dispatch/system_testing/browser.rb +20 -19
- data/lib/action_dispatch/system_testing/driver.rb +13 -21
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +27 -16
- data/lib/action_dispatch/testing/assertion_response.rb +1 -1
- data/lib/action_dispatch/testing/assertions/response.rb +13 -6
- data/lib/action_dispatch/testing/assertions/routing.rb +67 -28
- data/lib/action_dispatch/testing/assertions.rb +3 -1
- data/lib/action_dispatch/testing/integration.rb +27 -17
- data/lib/action_dispatch/testing/request_encoder.rb +4 -1
- data/lib/action_dispatch/testing/test_process.rb +4 -3
- data/lib/action_dispatch/testing/test_request.rb +1 -1
- data/lib/action_dispatch/testing/test_response.rb +23 -9
- data/lib/action_dispatch.rb +37 -4
- data/lib/action_pack/gem_version.rb +4 -4
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_pack.rb +1 -1
- metadata +64 -28
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -16,11 +16,11 @@ It consists of several modules:
|
|
16
16
|
subclassed to implement filters and actions to handle requests. The result
|
17
17
|
of an action is typically content generated from views.
|
18
18
|
|
19
|
-
With the Ruby on Rails framework, users only directly interface with the
|
19
|
+
With the Ruby on \Rails framework, users only directly interface with the
|
20
20
|
Action Controller module. Necessary Action Dispatch functionality is activated
|
21
21
|
by default and Action View rendering is implicitly triggered by Action
|
22
22
|
Controller. However, these modules are designed to function on their own and
|
23
|
-
can be used outside of Rails.
|
23
|
+
can be used outside of \Rails.
|
24
24
|
|
25
25
|
You can read more about Action Pack in the {Action Controller Overview}[https://guides.rubyonrails.org/action_controller_overview.html] guide.
|
26
26
|
|
@@ -26,6 +26,8 @@ module AbstractController
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
# = Abstract Controller \Base
|
30
|
+
#
|
29
31
|
# AbstractController::Base is a low-level API. Nobody should be
|
30
32
|
# using it directly, and subclasses (like ActionController::Base) are
|
31
33
|
# expected to provide their own +render+ method, since rendering means
|
@@ -70,12 +72,17 @@ module AbstractController
|
|
70
72
|
# instance methods on that abstract class. Public instance methods of
|
71
73
|
# a controller would normally be considered action methods, so methods
|
72
74
|
# declared on abstract classes are being removed.
|
73
|
-
# (
|
75
|
+
# (ActionController::Metal and ActionController::Base are defined as abstract)
|
74
76
|
def internal_methods
|
75
77
|
controller = self
|
78
|
+
methods = []
|
76
79
|
|
77
|
-
|
78
|
-
|
80
|
+
until controller.abstract?
|
81
|
+
methods += controller.public_instance_methods(false)
|
82
|
+
controller = controller.superclass
|
83
|
+
end
|
84
|
+
|
85
|
+
controller.public_instance_methods(true) - methods
|
79
86
|
end
|
80
87
|
|
81
88
|
# A list of method names that should be considered actions. This
|
@@ -89,14 +96,11 @@ module AbstractController
|
|
89
96
|
def action_methods
|
90
97
|
@action_methods ||= begin
|
91
98
|
# All public instance methods of this class, including ancestors
|
92
|
-
methods
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
public_instance_methods(false))
|
97
|
-
|
99
|
+
# except for public instance methods of Base and its ancestors.
|
100
|
+
methods = public_instance_methods(true) - internal_methods
|
101
|
+
# Be sure to include shadowed public instance methods of this class.
|
102
|
+
methods.concat(public_instance_methods(false))
|
98
103
|
methods.map!(&:to_s)
|
99
|
-
|
100
104
|
methods.to_set
|
101
105
|
end
|
102
106
|
end
|
@@ -127,11 +131,16 @@ module AbstractController
|
|
127
131
|
super
|
128
132
|
clear_action_methods!
|
129
133
|
end
|
134
|
+
|
135
|
+
def eager_load! # :nodoc:
|
136
|
+
action_methods
|
137
|
+
nil
|
138
|
+
end
|
130
139
|
end
|
131
140
|
|
132
141
|
abstract!
|
133
142
|
|
134
|
-
# Calls the action going through the entire
|
143
|
+
# Calls the action going through the entire Action Dispatch stack.
|
135
144
|
#
|
136
145
|
# The actual method that is called is determined by calling
|
137
146
|
# #method_for_action. If no method can handle the action, then an
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
module AbstractController
|
4
4
|
module Caching
|
5
|
+
# = Abstract Controller Caching \Fragments
|
6
|
+
#
|
5
7
|
# Fragment caching is used for caching various blocks within
|
6
8
|
# views without caching the entire action as a whole. This is
|
7
9
|
# useful when certain elements of an action change frequently or
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module AbstractController
|
4
|
-
# = Abstract Controller Callbacks
|
4
|
+
# = Abstract Controller \Callbacks
|
5
5
|
#
|
6
6
|
# Abstract Controller provides hooks during the life cycle of a controller action.
|
7
7
|
# Callbacks allow you to trigger logic during this cycle. Available callbacks are:
|
@@ -33,14 +33,36 @@ module AbstractController
|
|
33
33
|
define_callbacks :process_action,
|
34
34
|
terminator: ->(controller, result_lambda) { result_lambda.call; controller.performed? },
|
35
35
|
skip_after_callbacks_if_terminated: true
|
36
|
+
mattr_accessor :raise_on_missing_callback_actions, default: false
|
36
37
|
end
|
37
38
|
|
38
39
|
class ActionFilter # :nodoc:
|
39
|
-
def initialize(actions)
|
40
|
+
def initialize(filters, conditional_key, actions)
|
41
|
+
@filters = filters.to_a
|
42
|
+
@conditional_key = conditional_key
|
40
43
|
@actions = Array(actions).map(&:to_s).to_set
|
41
44
|
end
|
42
45
|
|
43
46
|
def match?(controller)
|
47
|
+
if controller.raise_on_missing_callback_actions
|
48
|
+
missing_action = @actions.find { |action| !controller.available_action?(action) }
|
49
|
+
if missing_action
|
50
|
+
filter_names = @filters.length == 1 ? @filters.first.inspect : @filters.inspect
|
51
|
+
|
52
|
+
message = <<~MSG
|
53
|
+
The #{missing_action} action could not be found for the #{filter_names}
|
54
|
+
callback on #{controller.class.name}, but it is listed in the controller's
|
55
|
+
#{@conditional_key.inspect} option.
|
56
|
+
|
57
|
+
Raising for missing callback actions is a new default in Rails 7.1, if you'd
|
58
|
+
like to turn this off you can delete the option from the environment configurations
|
59
|
+
or set `config.action_controller.raise_on_missing_callback_actions` to `false`.
|
60
|
+
MSG
|
61
|
+
|
62
|
+
raise ActionNotFound.new(message, controller, missing_action)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
44
66
|
@actions.include?(controller.action_name)
|
45
67
|
end
|
46
68
|
|
@@ -75,9 +97,10 @@ module AbstractController
|
|
75
97
|
end
|
76
98
|
|
77
99
|
def _normalize_callback_option(options, from, to) # :nodoc:
|
78
|
-
if
|
79
|
-
|
80
|
-
|
100
|
+
if from_value = options.delete(from)
|
101
|
+
filters = options[:filters]
|
102
|
+
from_value = ActionFilter.new(filters, from, from_value)
|
103
|
+
options[to] = Array(options[to]).unshift(from_value)
|
81
104
|
end
|
82
105
|
end
|
83
106
|
|
@@ -95,8 +118,10 @@ module AbstractController
|
|
95
118
|
# * <tt>options</tt> - A hash of options to be used when adding the callback.
|
96
119
|
def _insert_callbacks(callbacks, block = nil)
|
97
120
|
options = callbacks.extract_options!
|
98
|
-
_normalize_callback_options(options)
|
99
121
|
callbacks.push(block) if block
|
122
|
+
options[:filters] = callbacks
|
123
|
+
_normalize_callback_options(options)
|
124
|
+
options.delete(:filters)
|
100
125
|
callbacks.each do |callback|
|
101
126
|
yield callback, options
|
102
127
|
end
|
@@ -5,6 +5,7 @@ require "active_support/core_ext/name_error"
|
|
5
5
|
|
6
6
|
module AbstractController
|
7
7
|
module Helpers
|
8
|
+
include ActiveSupport::Deprecation::DeprecatedConstantAccessor
|
8
9
|
extend ActiveSupport::Concern
|
9
10
|
|
10
11
|
included do
|
@@ -23,7 +24,7 @@ module AbstractController
|
|
23
24
|
self._helpers = define_helpers_module(self)
|
24
25
|
end
|
25
26
|
|
26
|
-
class
|
27
|
+
class DeprecatedMissingHelperError < LoadError
|
27
28
|
def initialize(error, path)
|
28
29
|
@error = error
|
29
30
|
@path = "helpers/#{path}.rb"
|
@@ -36,11 +37,46 @@ module AbstractController
|
|
36
37
|
end
|
37
38
|
end
|
38
39
|
end
|
40
|
+
deprecate_constant "MissingHelperError", "AbstractController::Helpers::DeprecatedMissingHelperError",
|
41
|
+
message: "AbstractController::Helpers::MissingHelperError has been deprecated. If a Helper is not present, a NameError will be raised instead.",
|
42
|
+
deprecator: AbstractController.deprecator
|
39
43
|
|
40
44
|
def _helpers
|
41
45
|
self.class._helpers
|
42
46
|
end
|
43
47
|
|
48
|
+
module Resolution # :nodoc:
|
49
|
+
def modules_for_helpers(modules_or_helper_prefixes)
|
50
|
+
modules_or_helper_prefixes.flatten.map! do |module_or_helper_prefix|
|
51
|
+
case module_or_helper_prefix
|
52
|
+
when Module
|
53
|
+
module_or_helper_prefix
|
54
|
+
when String, Symbol
|
55
|
+
helper_prefix = module_or_helper_prefix.to_s
|
56
|
+
helper_prefix = helper_prefix.camelize unless helper_prefix.start_with?(/[A-Z]/)
|
57
|
+
"#{helper_prefix}Helper".constantize
|
58
|
+
else
|
59
|
+
raise ArgumentError, "helper must be a String, Symbol, or Module"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def all_helpers_from_path(path)
|
65
|
+
helpers = Array(path).flat_map do |_path|
|
66
|
+
names = Dir["#{_path}/**/*_helper.rb"].map { |file| file[_path.to_s.size + 1..-"_helper.rb".size - 1] }
|
67
|
+
names.sort!
|
68
|
+
end
|
69
|
+
helpers.uniq!
|
70
|
+
helpers
|
71
|
+
end
|
72
|
+
|
73
|
+
def helper_modules_from_paths(paths)
|
74
|
+
modules_for_helpers(all_helpers_from_path(paths))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
extend Resolution
|
79
|
+
|
44
80
|
module ClassMethods
|
45
81
|
# When a class is inherited, wrap its helper module in a new module.
|
46
82
|
# This ensures that the parent class's module can be changed
|
@@ -55,6 +91,30 @@ module AbstractController
|
|
55
91
|
|
56
92
|
attr_writer :_helpers
|
57
93
|
|
94
|
+
include Resolution
|
95
|
+
|
96
|
+
##
|
97
|
+
# :method: modules_for_helpers
|
98
|
+
# :call-seq: modules_for_helpers(modules_or_helper_prefixes)
|
99
|
+
#
|
100
|
+
# Given an array of values like the ones accepted by +helper+, this method
|
101
|
+
# returns an array with the corresponding modules, in the same order.
|
102
|
+
#
|
103
|
+
#--
|
104
|
+
# Implemented by Resolution#modules_for_helpers.
|
105
|
+
|
106
|
+
##
|
107
|
+
# :method: all_helpers_from_path
|
108
|
+
# :call-seq: all_helpers_from_path(path)
|
109
|
+
#
|
110
|
+
# Returns a list of helper names in a given path.
|
111
|
+
#
|
112
|
+
# ActionController::Base.all_helpers_from_path 'app/helpers'
|
113
|
+
# # => ["application", "chart", "rubygems"]
|
114
|
+
#
|
115
|
+
#--
|
116
|
+
# Implemented by Resolution#all_helpers_from_path.
|
117
|
+
|
58
118
|
# Declare a controller method as a helper. For example, the following
|
59
119
|
# makes the +current_user+ and +logged_in?+ controller methods available
|
60
120
|
# to the view:
|
@@ -168,23 +228,6 @@ module AbstractController
|
|
168
228
|
default_helper_module! unless anonymous?
|
169
229
|
end
|
170
230
|
|
171
|
-
# Given an array of values like the ones accepted by +helper+, this method
|
172
|
-
# returns an array with the corresponding modules, in the same order.
|
173
|
-
def modules_for_helpers(modules_or_helper_prefixes)
|
174
|
-
modules_or_helper_prefixes.flatten.map! do |module_or_helper_prefix|
|
175
|
-
case module_or_helper_prefix
|
176
|
-
when Module
|
177
|
-
module_or_helper_prefix
|
178
|
-
when String, Symbol
|
179
|
-
helper_prefix = module_or_helper_prefix.to_s
|
180
|
-
helper_prefix = helper_prefix.camelize unless helper_prefix.start_with?(/[A-Z]/)
|
181
|
-
"#{helper_prefix}Helper".constantize
|
182
|
-
else
|
183
|
-
raise ArgumentError, "helper must be a String, Symbol, or Module"
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
231
|
def _helpers_for_modification
|
189
232
|
unless @_helpers
|
190
233
|
self._helpers = define_helpers_module(self, superclass._helpers)
|
@@ -10,26 +10,11 @@ module AbstractController
|
|
10
10
|
define_method(:inherited) do |klass|
|
11
11
|
super(klass)
|
12
12
|
|
13
|
-
namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
|
14
|
-
actual_routes = namespace ? namespace.railtie_routes_url_helpers._routes : routes
|
15
|
-
|
16
|
-
if namespace
|
13
|
+
if namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
|
17
14
|
klass.include(namespace.railtie_routes_url_helpers(include_path_helpers))
|
18
15
|
else
|
19
16
|
klass.include(routes.url_helpers(include_path_helpers))
|
20
17
|
end
|
21
|
-
|
22
|
-
# In the case that we have ex.
|
23
|
-
# class A::Foo < ApplicationController
|
24
|
-
# class Bar < A::Foo
|
25
|
-
# We will need to redefine _routes because it will not be correct
|
26
|
-
# via inheritance.
|
27
|
-
unless klass._routes.equal?(actual_routes)
|
28
|
-
klass.redefine_singleton_method(:_routes) { actual_routes }
|
29
|
-
klass.include(Module.new do
|
30
|
-
define_method(:_routes) { @_routes || actual_routes }
|
31
|
-
end)
|
32
|
-
end
|
33
18
|
end
|
34
19
|
end
|
35
20
|
end
|
@@ -7,7 +7,7 @@ require "set"
|
|
7
7
|
|
8
8
|
module AbstractController
|
9
9
|
class DoubleRenderError < Error
|
10
|
-
DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...)
|
10
|
+
DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...); return\"."
|
11
11
|
|
12
12
|
def initialize(message = nil)
|
13
13
|
super(message || DEFAULT_MESSAGE)
|
@@ -68,8 +68,8 @@ module AbstractController
|
|
68
68
|
|
69
69
|
private
|
70
70
|
# Normalize args by converting <tt>render "foo"</tt> to
|
71
|
-
# <tt>render :
|
72
|
-
# <tt>render :
|
71
|
+
# <tt>render action: "foo"</tt> and <tt>render "foo/bar"</tt> to
|
72
|
+
# <tt>render file: "foo/bar"</tt>.
|
73
73
|
def _normalize_args(action = nil, options = {}) # :doc:
|
74
74
|
if action.respond_to?(:permitted?)
|
75
75
|
if action.permitted?
|
@@ -4,8 +4,6 @@ require "active_support/html_safe_translation"
|
|
4
4
|
|
5
5
|
module AbstractController
|
6
6
|
module Translation
|
7
|
-
mattr_accessor :raise_on_missing_translations, default: false
|
8
|
-
|
9
7
|
# Delegates to <tt>I18n.translate</tt>.
|
10
8
|
#
|
11
9
|
# When the given key starts with a period, it will be scoped by the current
|
@@ -23,8 +21,6 @@ module AbstractController
|
|
23
21
|
key = "#{path}.#{action_name}#{key}"
|
24
22
|
end
|
25
23
|
|
26
|
-
i18n_raise = options.fetch(:raise, self.raise_on_missing_translations)
|
27
|
-
|
28
24
|
if options[:default]
|
29
25
|
options[:default] = [options[:default]] unless options[:default].is_a?(Array)
|
30
26
|
options[:default] = options[:default].map do |value|
|
@@ -32,18 +28,7 @@ module AbstractController
|
|
32
28
|
end
|
33
29
|
end
|
34
30
|
|
35
|
-
|
36
|
-
options[:default] = [] unless options[:default]
|
37
|
-
options[:default] << MISSING_TRANSLATION
|
38
|
-
end
|
39
|
-
|
40
|
-
result = ActiveSupport::HtmlSafeTranslation.translate(key, **options, raise: i18n_raise)
|
41
|
-
|
42
|
-
if result == MISSING_TRANSLATION
|
43
|
-
+"translation missing: #{key}"
|
44
|
-
else
|
45
|
-
result
|
46
|
-
end
|
31
|
+
ActiveSupport::HtmlSafeTranslation.translate(key, **options)
|
47
32
|
end
|
48
33
|
alias :t :translate
|
49
34
|
|
@@ -52,9 +37,5 @@ module AbstractController
|
|
52
37
|
I18n.localize(object, **options)
|
53
38
|
end
|
54
39
|
alias :l :localize
|
55
|
-
|
56
|
-
private
|
57
|
-
MISSING_TRANSLATION = -(2**60)
|
58
|
-
private_constant :MISSING_TRANSLATION
|
59
40
|
end
|
60
41
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module AbstractController
|
4
|
+
# = URL For
|
5
|
+
#
|
4
6
|
# Includes +url_for+ into the host class (e.g. an abstract controller or mailer). The class
|
5
7
|
# has to provide a +RouteSet+ by implementing the <tt>_routes</tt> methods. Otherwise, an
|
6
8
|
# exception will be raised.
|
data/lib/abstract_controller.rb
CHANGED
@@ -4,6 +4,7 @@ require "action_pack"
|
|
4
4
|
require "active_support"
|
5
5
|
require "active_support/rails"
|
6
6
|
require "active_support/i18n"
|
7
|
+
require "abstract_controller/deprecator"
|
7
8
|
|
8
9
|
module AbstractController
|
9
10
|
extend ActiveSupport::Autoload
|
@@ -24,5 +25,10 @@ module AbstractController
|
|
24
25
|
def self.eager_load!
|
25
26
|
super
|
26
27
|
AbstractController::Caching.eager_load!
|
28
|
+
AbstractController::Base.descendants.each do |controller|
|
29
|
+
unless controller.abstract?
|
30
|
+
controller.eager_load!
|
31
|
+
end
|
32
|
+
end
|
27
33
|
end
|
28
34
|
end
|
@@ -5,6 +5,8 @@ require "action_controller"
|
|
5
5
|
require "action_controller/log_subscriber"
|
6
6
|
|
7
7
|
module ActionController
|
8
|
+
# = Action Controller \API
|
9
|
+
#
|
8
10
|
# API Controller is a lightweight version of ActionController::Base,
|
9
11
|
# created for applications that don't require all functionalities that a complete
|
10
12
|
# \Rails controller provides, allowing you to create controllers with just the
|
@@ -19,7 +21,7 @@ module ActionController
|
|
19
21
|
# your application, they're just not part of the default API controller stack.
|
20
22
|
#
|
21
23
|
# Normally, +ApplicationController+ is the only controller that inherits from
|
22
|
-
#
|
24
|
+
# +ActionController::API+. All other controllers in turn inherit from
|
23
25
|
# +ApplicationController+.
|
24
26
|
#
|
25
27
|
# A sample controller could look like this:
|
@@ -62,7 +64,7 @@ module ActionController
|
|
62
64
|
#
|
63
65
|
# In some scenarios you may want to add back some functionality provided by
|
64
66
|
# ActionController::Base that is not present by default in
|
65
|
-
#
|
67
|
+
# +ActionController::API+, for instance <tt>MimeResponds</tt>. This
|
66
68
|
# module gives you the <tt>respond_to</tt> method. Adding it is quite simple,
|
67
69
|
# you just need to include the module in a specific controller or in
|
68
70
|
# +ApplicationController+ in case you want it available in your entire
|
@@ -85,7 +87,7 @@ module ActionController
|
|
85
87
|
#
|
86
88
|
# Make sure to check the modules included in ActionController::Base
|
87
89
|
# if you want to use any other functionality that is not provided
|
88
|
-
# by
|
90
|
+
# by +ActionController::API+ out of the box.
|
89
91
|
class API < Metal
|
90
92
|
abstract!
|
91
93
|
|
@@ -5,11 +5,13 @@ require "action_controller/log_subscriber"
|
|
5
5
|
require "action_controller/metal/params_wrapper"
|
6
6
|
|
7
7
|
module ActionController
|
8
|
+
# = Action Controller \Base
|
9
|
+
#
|
8
10
|
# Action Controllers are the core of a web request in \Rails. They are made up of one or more actions that are executed
|
9
11
|
# on request and then either it renders a template or redirects to another action. An action is defined as a public method
|
10
12
|
# on the controller, which will automatically be made accessible to the web-server through \Rails Routes.
|
11
13
|
#
|
12
|
-
# By default, only the ApplicationController in a \Rails application inherits from
|
14
|
+
# By default, only the ApplicationController in a \Rails application inherits from +ActionController::Base+. All other
|
13
15
|
# controllers inherit from ApplicationController. This gives you one class to configure things such as
|
14
16
|
# request forgery protection and filtering of sensitive request parameters.
|
15
17
|
#
|
@@ -167,22 +169,6 @@ module ActionController
|
|
167
169
|
class Base < Metal
|
168
170
|
abstract!
|
169
171
|
|
170
|
-
# We document the request and response methods here because albeit they are
|
171
|
-
# implemented in ActionController::Metal, the type of the returned objects
|
172
|
-
# is unknown at that level.
|
173
|
-
|
174
|
-
##
|
175
|
-
# :method: request
|
176
|
-
#
|
177
|
-
# Returns an ActionDispatch::Request instance that represents the
|
178
|
-
# current request.
|
179
|
-
|
180
|
-
##
|
181
|
-
# :method: response
|
182
|
-
#
|
183
|
-
# Returns an ActionDispatch::Response that represents the current
|
184
|
-
# response.
|
185
|
-
|
186
172
|
# Shortcut helper that returns all the modules included in
|
187
173
|
# ActionController::Base except the ones passed as arguments:
|
188
174
|
#
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionController
|
4
|
+
# = Action Controller Form Builder
|
5
|
+
#
|
4
6
|
# Override the default form builder for all views rendered by this
|
5
7
|
# controller and any of its descendants. Accepts a subclass of
|
6
8
|
# ActionView::Helpers::FormBuilder.
|
@@ -8,7 +8,10 @@ module ActionController
|
|
8
8
|
return unless logger.info?
|
9
9
|
|
10
10
|
payload = event.payload
|
11
|
-
params
|
11
|
+
params = {}
|
12
|
+
payload[:params].each_pair do |k, v|
|
13
|
+
params[k] = v unless INTERNAL_PARAMS.include?(k)
|
14
|
+
end
|
12
15
|
format = payload[:format]
|
13
16
|
format = format.to_s.upcase if format.is_a?(Symbol)
|
14
17
|
format = "*/*" if format.nil?
|
@@ -16,6 +19,7 @@ module ActionController
|
|
16
19
|
info "Processing by #{payload[:controller]}##{payload[:action]} as #{format}"
|
17
20
|
info " Parameters: #{params.inspect}" unless params.empty?
|
18
21
|
end
|
22
|
+
subscribe_log_level :start_processing, :info
|
19
23
|
|
20
24
|
def process_action(event)
|
21
25
|
info do
|
@@ -29,29 +33,34 @@ module ActionController
|
|
29
33
|
|
30
34
|
additions << "Allocations: #{event.allocations}"
|
31
35
|
|
32
|
-
message = +"Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms"
|
33
|
-
|
36
|
+
message = +"Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms" \
|
37
|
+
" (#{additions.join(" | ")})"
|
34
38
|
message << "\n\n" if defined?(Rails.env) && Rails.env.development?
|
35
39
|
|
36
40
|
message
|
37
41
|
end
|
38
42
|
end
|
43
|
+
subscribe_log_level :process_action, :info
|
39
44
|
|
40
45
|
def halted_callback(event)
|
41
46
|
info { "Filter chain halted as #{event.payload[:filter].inspect} rendered or redirected" }
|
42
47
|
end
|
48
|
+
subscribe_log_level :halted_callback, :info
|
43
49
|
|
44
50
|
def send_file(event)
|
45
51
|
info { "Sent file #{event.payload[:path]} (#{event.duration.round(1)}ms)" }
|
46
52
|
end
|
53
|
+
subscribe_log_level :send_file, :info
|
47
54
|
|
48
55
|
def redirect_to(event)
|
49
56
|
info { "Redirected to #{event.payload[:location]}" }
|
50
57
|
end
|
58
|
+
subscribe_log_level :redirect_to, :info
|
51
59
|
|
52
60
|
def send_data(event)
|
53
61
|
info { "Sent data #{event.payload[:filename]} (#{event.duration.round(1)}ms)" }
|
54
62
|
end
|
63
|
+
subscribe_log_level :send_data, :info
|
55
64
|
|
56
65
|
def unpermitted_parameters(event)
|
57
66
|
debug do
|
@@ -61,15 +70,18 @@ module ActionController
|
|
61
70
|
color("Unpermitted parameter#{'s' if unpermitted_keys.size > 1}: #{display_unpermitted_keys}. Context: { #{context} }", RED)
|
62
71
|
end
|
63
72
|
end
|
73
|
+
subscribe_log_level :unpermitted_parameters, :debug
|
64
74
|
|
65
75
|
%w(write_fragment read_fragment exist_fragment? expire_fragment).each do |method|
|
66
76
|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
77
|
+
# frozen_string_literal: true
|
67
78
|
def #{method}(event)
|
68
|
-
return unless
|
79
|
+
return unless ActionController::Base.enable_fragment_cache_logging
|
69
80
|
key = ActiveSupport::Cache.expand_cache_key(event.payload[:key] || event.payload[:path])
|
70
81
|
human_name = #{method.to_s.humanize.inspect}
|
71
82
|
info("\#{human_name} \#{key} (\#{event.duration.round(1)}ms)")
|
72
83
|
end
|
84
|
+
subscribe_log_level :#{method}, :info
|
73
85
|
METHOD
|
74
86
|
end
|
75
87
|
|
@@ -4,6 +4,8 @@ require "action_controller/metal/exceptions"
|
|
4
4
|
require "action_dispatch/http/content_disposition"
|
5
5
|
|
6
6
|
module ActionController # :nodoc:
|
7
|
+
# = Action Controller Data \Streaming
|
8
|
+
#
|
7
9
|
# Methods for sending arbitrary data and for streaming files to the browser,
|
8
10
|
# instead of rendering.
|
9
11
|
module DataStreaming
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionController
|
4
|
+
# = Action Controller Etag With \Flash
|
5
|
+
#
|
4
6
|
# When you're using the flash, it's generally used as a conditional on the view.
|
5
7
|
# This means the content of the view depends on the flash. Which in turn means
|
6
8
|
# that the ETag for a response should be computed with the content of the flash
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionController
|
4
|
+
# = Action Controller Etag With Template \Digest
|
5
|
+
#
|
4
6
|
# When our views change, they should bubble up into HTTP cache freshness
|
5
7
|
# and bust browser caches. So the template digest for the current action
|
6
8
|
# is automatically included in the ETag.
|
@@ -92,5 +92,13 @@ module ActionController
|
|
92
92
|
end
|
93
93
|
|
94
94
|
class MissingExactTemplate < UnknownFormat # :nodoc:
|
95
|
+
attr_reader :controller, :action_name
|
96
|
+
|
97
|
+
def initialize(message, controller, action_name)
|
98
|
+
@controller = controller
|
99
|
+
@action_name = action_name
|
100
|
+
|
101
|
+
super(message)
|
102
|
+
end
|
95
103
|
end
|
96
104
|
end
|