actionpack 6.1.7.5 → 7.1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +355 -435
- data/MIT-LICENSE +2 -1
- data/README.rdoc +6 -7
- data/lib/abstract_controller/asset_paths.rb +1 -1
- data/lib/abstract_controller/base.rb +33 -37
- data/lib/abstract_controller/caching/fragments.rb +4 -2
- data/lib/abstract_controller/caching.rb +1 -1
- data/lib/abstract_controller/callbacks.rb +50 -11
- data/lib/abstract_controller/collector.rb +2 -2
- data/lib/abstract_controller/deprecator.rb +7 -0
- data/lib/abstract_controller/error.rb +1 -1
- data/lib/abstract_controller/helpers.rb +78 -30
- data/lib/abstract_controller/logger.rb +1 -1
- data/lib/abstract_controller/railties/routes_helpers.rb +3 -16
- data/lib/abstract_controller/rendering.rb +12 -14
- data/lib/abstract_controller/translation.rb +26 -7
- data/lib/abstract_controller/url_for.rb +6 -6
- data/lib/abstract_controller.rb +6 -0
- data/lib/action_controller/api.rb +12 -10
- data/lib/action_controller/base.rb +8 -21
- data/lib/action_controller/caching.rb +2 -0
- data/lib/action_controller/deprecator.rb +7 -0
- data/lib/action_controller/form_builder.rb +4 -2
- data/lib/action_controller/log_subscriber.rb +20 -7
- data/lib/action_controller/metal/basic_implicit_render.rb +3 -1
- data/lib/action_controller/metal/conditional_get.rb +137 -102
- data/lib/action_controller/metal/content_security_policy.rb +37 -3
- data/lib/action_controller/metal/cookies.rb +1 -1
- data/lib/action_controller/metal/data_streaming.rb +25 -31
- data/lib/action_controller/metal/default_headers.rb +2 -0
- data/lib/action_controller/metal/etag_with_flash.rb +3 -1
- data/lib/action_controller/metal/etag_with_template_digest.rb +2 -0
- data/lib/action_controller/metal/exceptions.rb +27 -30
- data/lib/action_controller/metal/flash.rb +6 -2
- data/lib/action_controller/metal/head.rb +9 -7
- data/lib/action_controller/metal/helpers.rb +5 -16
- data/lib/action_controller/metal/http_authentication.rb +78 -42
- data/lib/action_controller/metal/implicit_render.rb +5 -3
- data/lib/action_controller/metal/instrumentation.rb +62 -50
- data/lib/action_controller/metal/live.rb +67 -2
- data/lib/action_controller/metal/mime_responds.rb +5 -5
- data/lib/action_controller/metal/params_wrapper.rb +24 -13
- data/lib/action_controller/metal/permissions_policy.rb +20 -29
- data/lib/action_controller/metal/redirecting.rb +96 -23
- data/lib/action_controller/metal/renderers.rb +14 -15
- data/lib/action_controller/metal/rendering.rb +121 -16
- data/lib/action_controller/metal/request_forgery_protection.rb +208 -68
- data/lib/action_controller/metal/rescue.rb +7 -4
- data/lib/action_controller/metal/streaming.rb +74 -36
- data/lib/action_controller/metal/strong_parameters.rb +254 -151
- data/lib/action_controller/metal/testing.rb +9 -2
- data/lib/action_controller/metal/url_for.rb +10 -5
- data/lib/action_controller/metal.rb +89 -34
- data/lib/action_controller/railtie.rb +66 -9
- data/lib/action_controller/renderer.rb +99 -85
- data/lib/action_controller/test_case.rb +42 -11
- data/lib/action_controller.rb +10 -6
- data/lib/action_dispatch/constants.rb +32 -0
- data/lib/action_dispatch/deprecator.rb +7 -0
- data/lib/action_dispatch/http/cache.rb +21 -16
- data/lib/action_dispatch/http/content_security_policy.rb +122 -44
- data/lib/action_dispatch/http/filter_parameters.rb +14 -23
- data/lib/action_dispatch/http/headers.rb +3 -1
- data/lib/action_dispatch/http/mime_negotiation.rb +25 -15
- data/lib/action_dispatch/http/mime_type.rb +43 -22
- data/lib/action_dispatch/http/mime_types.rb +3 -1
- data/lib/action_dispatch/http/parameters.rb +6 -6
- data/lib/action_dispatch/http/permissions_policy.rb +57 -19
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +75 -51
- data/lib/action_dispatch/http/response.rb +81 -77
- data/lib/action_dispatch/http/upload.rb +15 -2
- data/lib/action_dispatch/http/url.rb +11 -19
- data/lib/action_dispatch/journey/formatter.rb +8 -2
- data/lib/action_dispatch/journey/gtg/builder.rb +11 -12
- data/lib/action_dispatch/journey/gtg/simulator.rb +10 -4
- data/lib/action_dispatch/journey/gtg/transition_table.rb +77 -21
- data/lib/action_dispatch/journey/nodes/node.rb +70 -5
- data/lib/action_dispatch/journey/path/pattern.rb +36 -27
- data/lib/action_dispatch/journey/route.rb +8 -14
- data/lib/action_dispatch/journey/router/utils.rb +2 -2
- data/lib/action_dispatch/journey/router.rb +10 -9
- data/lib/action_dispatch/journey/routes.rb +5 -5
- data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
- data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
- data/lib/action_dispatch/log_subscriber.rb +23 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +5 -7
- 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 +97 -107
- data/lib/action_dispatch/middleware/debug_exceptions.rb +31 -28
- data/lib/action_dispatch/middleware/debug_locks.rb +7 -4
- data/lib/action_dispatch/middleware/debug_view.rb +7 -2
- data/lib/action_dispatch/middleware/exception_wrapper.rb +190 -27
- data/lib/action_dispatch/middleware/executor.rb +3 -0
- data/lib/action_dispatch/middleware/flash.rb +24 -18
- data/lib/action_dispatch/middleware/host_authorization.rb +19 -20
- 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 +32 -19
- data/lib/action_dispatch/middleware/request_id.rb +5 -3
- data/lib/action_dispatch/middleware/server_timing.rb +76 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +6 -1
- data/lib/action_dispatch/middleware/session/cache_store.rb +2 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +19 -13
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +3 -1
- data/lib/action_dispatch/middleware/show_exceptions.rb +30 -25
- data/lib/action_dispatch/middleware/ssl.rb +18 -6
- data/lib/action_dispatch/middleware/stack.rb +34 -11
- data/lib/action_dispatch/middleware/static.rb +16 -16
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +5 -5
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -11
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +8 -1
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +10 -5
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +7 -3
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +9 -9
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +45 -18
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -15
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +6 -6
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +7 -7
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
- 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 +64 -55
- data/lib/action_dispatch/railtie.rb +20 -4
- data/lib/action_dispatch/request/session.rb +59 -19
- data/lib/action_dispatch/request/utils.rb +8 -3
- data/lib/action_dispatch/routing/inspector.rb +55 -7
- data/lib/action_dispatch/routing/mapper.rb +117 -107
- data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
- data/lib/action_dispatch/routing/redirection.rb +20 -8
- data/lib/action_dispatch/routing/route_set.rb +67 -27
- data/lib/action_dispatch/routing/routes_proxy.rb +11 -16
- data/lib/action_dispatch/routing/url_for.rb +29 -26
- data/lib/action_dispatch/routing.rb +12 -13
- data/lib/action_dispatch/system_test_case.rb +8 -8
- data/lib/action_dispatch/system_testing/browser.rb +20 -29
- data/lib/action_dispatch/system_testing/driver.rb +34 -18
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +35 -20
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +0 -8
- data/lib/action_dispatch/testing/assertion_response.rb +1 -1
- data/lib/action_dispatch/testing/assertions/response.rb +14 -7
- data/lib/action_dispatch/testing/assertions/routing.rb +70 -30
- data/lib/action_dispatch/testing/assertions.rb +3 -4
- data/lib/action_dispatch/testing/integration.rb +33 -25
- data/lib/action_dispatch/testing/request_encoder.rb +4 -1
- data/lib/action_dispatch/testing/test_process.rb +5 -30
- data/lib/action_dispatch/testing/test_request.rb +1 -1
- data/lib/action_dispatch/testing/test_response.rb +34 -2
- data/lib/action_dispatch.rb +38 -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 +67 -30
data/MIT-LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) David Heinemeier Hansson
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
a copy of this software and associated documentation files (the
|
@@ -18,3 +18,4 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
18
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
19
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
20
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README.rdoc
CHANGED
@@ -2,9 +2,8 @@
|
|
2
2
|
|
3
3
|
Action Pack is a framework for handling and responding to web requests. It
|
4
4
|
provides mechanisms for *routing* (mapping request URLs to actions), defining
|
5
|
-
*controllers* that implement actions, and generating responses
|
6
|
-
|
7
|
-
provides the view and controller layers in the MVC paradigm.
|
5
|
+
*controllers* that implement actions, and generating responses. In short, Action Pack
|
6
|
+
provides the controller layer in the MVC paradigm.
|
8
7
|
|
9
8
|
It consists of several modules:
|
10
9
|
|
@@ -17,11 +16,11 @@ It consists of several modules:
|
|
17
16
|
subclassed to implement filters and actions to handle requests. The result
|
18
17
|
of an action is typically content generated from views.
|
19
18
|
|
20
|
-
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
|
21
20
|
Action Controller module. Necessary Action Dispatch functionality is activated
|
22
21
|
by default and Action View rendering is implicitly triggered by Action
|
23
22
|
Controller. However, these modules are designed to function on their own and
|
24
|
-
can be used outside of Rails.
|
23
|
+
can be used outside of \Rails.
|
25
24
|
|
26
25
|
You can read more about Action Pack in the {Action Controller Overview}[https://guides.rubyonrails.org/action_controller_overview.html] guide.
|
27
26
|
|
@@ -31,7 +30,7 @@ The latest version of Action Pack can be installed with RubyGems:
|
|
31
30
|
|
32
31
|
$ gem install actionpack
|
33
32
|
|
34
|
-
Source code can be downloaded as part of the Rails project on GitHub:
|
33
|
+
Source code can be downloaded as part of the \Rails project on GitHub:
|
35
34
|
|
36
35
|
* https://github.com/rails/rails/tree/main/actionpack
|
37
36
|
|
@@ -49,7 +48,7 @@ API documentation is at:
|
|
49
48
|
|
50
49
|
* https://api.rubyonrails.org
|
51
50
|
|
52
|
-
Bug reports for the Ruby on Rails project can be filed here:
|
51
|
+
Bug reports for the Ruby on \Rails project can be filed here:
|
53
52
|
|
54
53
|
* https://github.com/rails/rails/issues
|
55
54
|
|
@@ -9,37 +9,25 @@ require "active_support/core_ext/module/attr_internal"
|
|
9
9
|
module AbstractController
|
10
10
|
# Raised when a non-existing controller action is triggered.
|
11
11
|
class ActionNotFound < StandardError
|
12
|
-
attr_reader :controller, :action
|
13
|
-
|
12
|
+
attr_reader :controller, :action # :nodoc:
|
13
|
+
|
14
|
+
def initialize(message = nil, controller = nil, action = nil) # :nodoc:
|
14
15
|
@controller = controller
|
15
16
|
@action = action
|
16
17
|
super(message)
|
17
18
|
end
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
@error = error
|
22
|
-
end
|
23
|
-
|
24
|
-
def corrections
|
25
|
-
if @error.action
|
26
|
-
maybe_these = @error.controller.class.action_methods
|
20
|
+
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
21
|
+
include DidYouMean::Correctable # :nodoc:
|
27
22
|
|
28
|
-
|
29
|
-
|
30
|
-
}.reverse.first(4)
|
31
|
-
else
|
32
|
-
[]
|
33
|
-
end
|
23
|
+
def corrections # :nodoc:
|
24
|
+
@corrections ||= DidYouMean::SpellChecker.new(dictionary: controller.class.action_methods).correct(action)
|
34
25
|
end
|
35
26
|
end
|
36
|
-
|
37
|
-
# We may not have DYM, and DYM might not let us register error handlers
|
38
|
-
if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
|
39
|
-
DidYouMean.correct_error(self, Correction)
|
40
|
-
end
|
41
27
|
end
|
42
28
|
|
29
|
+
# = Abstract Controller \Base
|
30
|
+
#
|
43
31
|
# AbstractController::Base is a low-level API. Nobody should be
|
44
32
|
# using it directly, and subclasses (like ActionController::Base) are
|
45
33
|
# expected to provide their own +render+ method, since rendering means
|
@@ -84,12 +72,17 @@ module AbstractController
|
|
84
72
|
# instance methods on that abstract class. Public instance methods of
|
85
73
|
# a controller would normally be considered action methods, so methods
|
86
74
|
# declared on abstract classes are being removed.
|
87
|
-
# (
|
75
|
+
# (ActionController::Metal and ActionController::Base are defined as abstract)
|
88
76
|
def internal_methods
|
89
77
|
controller = self
|
78
|
+
methods = []
|
90
79
|
|
91
|
-
|
92
|
-
|
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
|
93
86
|
end
|
94
87
|
|
95
88
|
# A list of method names that should be considered actions. This
|
@@ -103,14 +96,11 @@ module AbstractController
|
|
103
96
|
def action_methods
|
104
97
|
@action_methods ||= begin
|
105
98
|
# All public instance methods of this class, including ancestors
|
106
|
-
methods
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
public_instance_methods(false))
|
111
|
-
|
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))
|
112
103
|
methods.map!(&:to_s)
|
113
|
-
|
114
104
|
methods.to_set
|
115
105
|
end
|
116
106
|
end
|
@@ -141,11 +131,16 @@ module AbstractController
|
|
141
131
|
super
|
142
132
|
clear_action_methods!
|
143
133
|
end
|
134
|
+
|
135
|
+
def eager_load! # :nodoc:
|
136
|
+
action_methods
|
137
|
+
nil
|
138
|
+
end
|
144
139
|
end
|
145
140
|
|
146
141
|
abstract!
|
147
142
|
|
148
|
-
# Calls the action going through the entire
|
143
|
+
# Calls the action going through the entire Action Dispatch stack.
|
149
144
|
#
|
150
145
|
# The actual method that is called is determined by calling
|
151
146
|
# #method_for_action. If no method can handle the action, then an
|
@@ -164,13 +159,14 @@ module AbstractController
|
|
164
159
|
|
165
160
|
process_action(action_name, *args)
|
166
161
|
end
|
162
|
+
ruby2_keywords(:process)
|
167
163
|
|
168
|
-
# Delegates to the class' ::controller_path
|
164
|
+
# Delegates to the class's ::controller_path.
|
169
165
|
def controller_path
|
170
166
|
self.class.controller_path
|
171
167
|
end
|
172
168
|
|
173
|
-
# Delegates to the class' ::action_methods
|
169
|
+
# Delegates to the class's ::action_methods.
|
174
170
|
def action_methods
|
175
171
|
self.class.action_methods
|
176
172
|
end
|
@@ -191,7 +187,7 @@ module AbstractController
|
|
191
187
|
|
192
188
|
# Tests if a response body is set. Used to determine if the
|
193
189
|
# +process_action+ callback needs to be terminated in
|
194
|
-
#
|
190
|
+
# AbstractController::Callbacks.
|
195
191
|
def performed?
|
196
192
|
response_body
|
197
193
|
end
|
@@ -224,8 +220,8 @@ module AbstractController
|
|
224
220
|
#
|
225
221
|
# Notice that the first argument is the method to be dispatched
|
226
222
|
# which is *not* necessarily the same as the action name.
|
227
|
-
def process_action(
|
228
|
-
send_action(
|
223
|
+
def process_action(...)
|
224
|
+
send_action(...)
|
229
225
|
end
|
230
226
|
|
231
227
|
# Actually call the method associated with the action. Override
|
@@ -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
|
@@ -142,8 +144,8 @@ module AbstractController
|
|
142
144
|
end
|
143
145
|
end
|
144
146
|
|
145
|
-
def instrument_fragment_cache(name, key) # :nodoc:
|
146
|
-
ActiveSupport::Notifications.instrument("#{name}.#{instrument_name}", instrument_payload(key))
|
147
|
+
def instrument_fragment_cache(name, key, &block) # :nodoc:
|
148
|
+
ActiveSupport::Notifications.instrument("#{name}.#{instrument_name}", instrument_payload(key), &block)
|
147
149
|
end
|
148
150
|
end
|
149
151
|
end
|
@@ -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,42 @@ 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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
class ActionFilter # :nodoc:
|
40
|
+
def initialize(filters, conditional_key, actions)
|
41
|
+
@filters = filters.to_a
|
42
|
+
@conditional_key = conditional_key
|
43
|
+
@actions = Array(actions).map(&:to_s).to_set
|
43
44
|
end
|
45
|
+
|
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
|
+
|
66
|
+
@actions.include?(controller.action_name)
|
67
|
+
end
|
68
|
+
|
69
|
+
alias after match?
|
70
|
+
alias before match?
|
71
|
+
alias around match?
|
44
72
|
end
|
45
73
|
|
46
74
|
module ClassMethods
|
@@ -69,10 +97,10 @@ module AbstractController
|
|
69
97
|
end
|
70
98
|
|
71
99
|
def _normalize_callback_option(options, from, to) # :nodoc:
|
72
|
-
if
|
73
|
-
|
74
|
-
|
75
|
-
options[to] = Array(options[to]).unshift(
|
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)
|
76
104
|
end
|
77
105
|
end
|
78
106
|
|
@@ -90,8 +118,10 @@ module AbstractController
|
|
90
118
|
# * <tt>options</tt> - A hash of options to be used when adding the callback.
|
91
119
|
def _insert_callbacks(callbacks, block = nil)
|
92
120
|
options = callbacks.extract_options!
|
93
|
-
_normalize_callback_options(options)
|
94
121
|
callbacks.push(block) if block
|
122
|
+
options[:filters] = callbacks
|
123
|
+
_normalize_callback_options(options)
|
124
|
+
options.delete(:filters)
|
95
125
|
callbacks.each do |callback|
|
96
126
|
yield callback, options
|
97
127
|
end
|
@@ -220,5 +250,14 @@ module AbstractController
|
|
220
250
|
alias_method :"append_#{callback}_action", :"#{callback}_action"
|
221
251
|
end
|
222
252
|
end
|
253
|
+
|
254
|
+
private
|
255
|
+
# Override <tt>AbstractController::Base#process_action</tt> to run the
|
256
|
+
# <tt>process_action</tt> callbacks around the normal behavior.
|
257
|
+
def process_action(...)
|
258
|
+
run_callbacks(:process_action) do
|
259
|
+
super
|
260
|
+
end
|
261
|
+
end
|
223
262
|
end
|
224
263
|
end
|
@@ -10,7 +10,7 @@ module AbstractController
|
|
10
10
|
def #{sym}(*args, &block)
|
11
11
|
custom(Mime[:#{sym}], *args, &block)
|
12
12
|
end
|
13
|
-
ruby2_keywords(:#{sym})
|
13
|
+
ruby2_keywords(:#{sym})
|
14
14
|
RUBY
|
15
15
|
end
|
16
16
|
|
@@ -39,6 +39,6 @@ module AbstractController
|
|
39
39
|
super
|
40
40
|
end
|
41
41
|
end
|
42
|
-
ruby2_keywords(:method_missing)
|
42
|
+
ruby2_keywords(:method_missing)
|
43
43
|
end
|
44
44
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/dependencies"
|
4
|
+
require "active_support/core_ext/name_error"
|
4
5
|
|
5
6
|
module AbstractController
|
6
7
|
module Helpers
|
8
|
+
include ActiveSupport::Deprecation::DeprecatedConstantAccessor
|
7
9
|
extend ActiveSupport::Concern
|
8
10
|
|
9
11
|
included do
|
@@ -22,7 +24,7 @@ module AbstractController
|
|
22
24
|
self._helpers = define_helpers_module(self)
|
23
25
|
end
|
24
26
|
|
25
|
-
class
|
27
|
+
class DeprecatedMissingHelperError < LoadError
|
26
28
|
def initialize(error, path)
|
27
29
|
@error = error
|
28
30
|
@path = "helpers/#{path}.rb"
|
@@ -35,11 +37,46 @@ module AbstractController
|
|
35
37
|
end
|
36
38
|
end
|
37
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
|
38
43
|
|
39
44
|
def _helpers
|
40
45
|
self.class._helpers
|
41
46
|
end
|
42
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
|
+
|
43
80
|
module ClassMethods
|
44
81
|
# When a class is inherited, wrap its helper module in a new module.
|
45
82
|
# This ensures that the parent class's module can be changed
|
@@ -54,19 +91,44 @@ module AbstractController
|
|
54
91
|
|
55
92
|
attr_writer :_helpers
|
56
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
|
+
|
57
118
|
# Declare a controller method as a helper. For example, the following
|
58
119
|
# makes the +current_user+ and +logged_in?+ controller methods available
|
59
120
|
# to the view:
|
60
121
|
# class ApplicationController < ActionController::Base
|
61
122
|
# helper_method :current_user, :logged_in?
|
62
123
|
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
124
|
+
# private
|
125
|
+
# def current_user
|
126
|
+
# @current_user ||= User.find_by(id: session[:user])
|
127
|
+
# end
|
66
128
|
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
129
|
+
# def logged_in?
|
130
|
+
# current_user != nil
|
131
|
+
# end
|
70
132
|
# end
|
71
133
|
#
|
72
134
|
# In a view:
|
@@ -83,11 +145,14 @@ module AbstractController
|
|
83
145
|
file, line = location.path, location.lineno
|
84
146
|
|
85
147
|
methods.each do |method|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
148
|
+
# def current_user(*args, &block)
|
149
|
+
# controller.send(:'current_user', *args, &block)
|
150
|
+
# end
|
151
|
+
_helpers_for_modification.class_eval <<~ruby_eval.lines.map(&:strip).join(";"), file, line
|
152
|
+
def #{method}(*args, &block)
|
153
|
+
controller.send(:'#{method}', *args, &block)
|
154
|
+
end
|
155
|
+
ruby2_keywords(:'#{method}')
|
91
156
|
ruby_eval
|
92
157
|
end
|
93
158
|
end
|
@@ -109,7 +174,7 @@ module AbstractController
|
|
109
174
|
# The last two assume that <tt>"foo".camelize</tt> returns "Foo".
|
110
175
|
#
|
111
176
|
# When strings or symbols are passed, the method finds the actual module
|
112
|
-
# object using
|
177
|
+
# object using String#constantize. Therefore, if the module has not been
|
113
178
|
# yet loaded, it has to be autoloadable, which is normally the case.
|
114
179
|
#
|
115
180
|
# Namespaces are supported. The following calls include +Foo::BarHelper+:
|
@@ -163,23 +228,6 @@ module AbstractController
|
|
163
228
|
default_helper_module! unless anonymous?
|
164
229
|
end
|
165
230
|
|
166
|
-
# Given an array of values like the ones accepted by +helper+, this method
|
167
|
-
# returns an array with the corresponding modules, in the same order.
|
168
|
-
def modules_for_helpers(modules_or_helper_prefixes)
|
169
|
-
modules_or_helper_prefixes.flatten.map! do |module_or_helper_prefix|
|
170
|
-
case module_or_helper_prefix
|
171
|
-
when Module
|
172
|
-
module_or_helper_prefix
|
173
|
-
when String, Symbol
|
174
|
-
helper_prefix = module_or_helper_prefix.to_s
|
175
|
-
helper_prefix = helper_prefix.camelize unless helper_prefix.start_with?(/[A-Z]/)
|
176
|
-
"#{helper_prefix}Helper".constantize
|
177
|
-
else
|
178
|
-
raise ArgumentError, "helper must be a String, Symbol, or Module"
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
231
|
def _helpers_for_modification
|
184
232
|
unless @_helpers
|
185
233
|
self._helpers = define_helpers_module(self, superclass._helpers)
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/module/introspection"
|
4
|
+
|
3
5
|
module AbstractController
|
4
6
|
module Railties
|
5
7
|
module RoutesHelpers
|
@@ -8,26 +10,11 @@ module AbstractController
|
|
8
10
|
define_method(:inherited) do |klass|
|
9
11
|
super(klass)
|
10
12
|
|
11
|
-
namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
|
12
|
-
actual_routes = namespace ? namespace.railtie_routes_url_helpers._routes : routes
|
13
|
-
|
14
|
-
if namespace
|
13
|
+
if namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
|
15
14
|
klass.include(namespace.railtie_routes_url_helpers(include_path_helpers))
|
16
15
|
else
|
17
16
|
klass.include(routes.url_helpers(include_path_helpers))
|
18
17
|
end
|
19
|
-
|
20
|
-
# In the case that we have ex.
|
21
|
-
# class A::Foo < ApplicationController
|
22
|
-
# class Bar < A::Foo
|
23
|
-
# We will need to redefine _routes because it will not be correct
|
24
|
-
# via inheritance.
|
25
|
-
unless klass._routes.equal?(actual_routes)
|
26
|
-
klass.redefine_singleton_method(:_routes) { actual_routes }
|
27
|
-
klass.include(Module.new do
|
28
|
-
define_method(:_routes) { @_routes || actual_routes }
|
29
|
-
end)
|
30
|
-
end
|
31
18
|
end
|
32
19
|
end
|
33
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)
|
@@ -18,8 +18,10 @@ module AbstractController
|
|
18
18
|
extend ActiveSupport::Concern
|
19
19
|
include ActionView::ViewPaths
|
20
20
|
|
21
|
-
# Normalizes arguments
|
21
|
+
# Normalizes arguments and options, and then delegates to render_to_body and
|
22
22
|
# sticks the result in <tt>self.response_body</tt>.
|
23
|
+
#
|
24
|
+
# Supported options depend on the underlying +render_to_body+ implementation.
|
23
25
|
def render(*args, &block)
|
24
26
|
options = _normalize_render(*args, &block)
|
25
27
|
rendered_body = render_to_body(options)
|
@@ -32,16 +34,12 @@ module AbstractController
|
|
32
34
|
self.response_body = rendered_body
|
33
35
|
end
|
34
36
|
|
35
|
-
#
|
36
|
-
#
|
37
|
-
# It is similar to render, except that it does not
|
38
|
-
# set the +response_body+ and it should be guaranteed
|
39
|
-
# to always return a string.
|
37
|
+
# Similar to #render, but only returns the rendered template as a string,
|
38
|
+
# instead of setting +self.response_body+.
|
40
39
|
#
|
41
|
-
# If a component extends the semantics of +response_body+
|
42
|
-
#
|
43
|
-
#
|
44
|
-
# overridden in order to still return a string.
|
40
|
+
# If a component extends the semantics of +response_body+ (as ActionController
|
41
|
+
# extends it to be anything that responds to the method each), this method
|
42
|
+
# needs to be overridden in order to still return a string.
|
45
43
|
def render_to_string(*args, &block)
|
46
44
|
options = _normalize_render(*args, &block)
|
47
45
|
render_to_body(options)
|
@@ -51,7 +49,7 @@ module AbstractController
|
|
51
49
|
def render_to_body(options = {})
|
52
50
|
end
|
53
51
|
|
54
|
-
# Returns Content-Type of rendered content.
|
52
|
+
# Returns +Content-Type+ of rendered content.
|
55
53
|
def rendered_format
|
56
54
|
Mime[:text]
|
57
55
|
end
|
@@ -70,8 +68,8 @@ module AbstractController
|
|
70
68
|
|
71
69
|
private
|
72
70
|
# Normalize args by converting <tt>render "foo"</tt> to
|
73
|
-
# <tt>render :
|
74
|
-
# <tt>render :
|
71
|
+
# <tt>render action: "foo"</tt> and <tt>render "foo/bar"</tt> to
|
72
|
+
# <tt>render file: "foo/bar"</tt>.
|
75
73
|
def _normalize_args(action = nil, options = {}) # :doc:
|
76
74
|
if action.respond_to?(:permitted?)
|
77
75
|
if action.permitted?
|