actionpack 7.1.3 → 7.2.1.1
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 +82 -501
- data/lib/abstract_controller/asset_paths.rb +2 -0
- data/lib/abstract_controller/base.rb +102 -98
- data/lib/abstract_controller/caching/fragments.rb +50 -53
- data/lib/abstract_controller/caching.rb +2 -0
- data/lib/abstract_controller/callbacks.rb +66 -64
- data/lib/abstract_controller/collector.rb +6 -6
- data/lib/abstract_controller/deprecator.rb +2 -0
- data/lib/abstract_controller/error.rb +2 -0
- data/lib/abstract_controller/helpers.rb +70 -85
- data/lib/abstract_controller/logger.rb +2 -0
- data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
- data/lib/abstract_controller/rendering.rb +13 -12
- data/lib/abstract_controller/translation.rb +15 -7
- data/lib/abstract_controller/url_for.rb +8 -6
- data/lib/abstract_controller.rb +2 -0
- data/lib/action_controller/api/api_rendering.rb +2 -0
- data/lib/action_controller/api.rb +74 -72
- data/lib/action_controller/base.rb +198 -126
- data/lib/action_controller/caching.rb +15 -12
- data/lib/action_controller/deprecator.rb +2 -0
- data/lib/action_controller/form_builder.rb +20 -17
- data/lib/action_controller/log_subscriber.rb +3 -1
- data/lib/action_controller/metal/allow_browser.rb +123 -0
- data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
- data/lib/action_controller/metal/conditional_get.rb +188 -174
- data/lib/action_controller/metal/content_security_policy.rb +25 -24
- data/lib/action_controller/metal/cookies.rb +4 -2
- data/lib/action_controller/metal/data_streaming.rb +64 -55
- data/lib/action_controller/metal/default_headers.rb +5 -3
- data/lib/action_controller/metal/etag_with_flash.rb +3 -1
- data/lib/action_controller/metal/etag_with_template_digest.rb +17 -15
- data/lib/action_controller/metal/exceptions.rb +11 -9
- data/lib/action_controller/metal/flash.rb +12 -10
- data/lib/action_controller/metal/head.rb +12 -10
- data/lib/action_controller/metal/helpers.rb +63 -55
- data/lib/action_controller/metal/http_authentication.rb +210 -205
- data/lib/action_controller/metal/implicit_render.rb +17 -15
- data/lib/action_controller/metal/instrumentation.rb +15 -12
- data/lib/action_controller/metal/live.rb +113 -107
- data/lib/action_controller/metal/logging.rb +6 -4
- data/lib/action_controller/metal/mime_responds.rb +151 -142
- data/lib/action_controller/metal/parameter_encoding.rb +34 -32
- data/lib/action_controller/metal/params_wrapper.rb +57 -59
- data/lib/action_controller/metal/permissions_policy.rb +13 -12
- data/lib/action_controller/metal/rate_limiting.rb +62 -0
- data/lib/action_controller/metal/redirecting.rb +108 -82
- data/lib/action_controller/metal/renderers.rb +50 -49
- data/lib/action_controller/metal/rendering.rb +103 -75
- data/lib/action_controller/metal/request_forgery_protection.rb +162 -133
- data/lib/action_controller/metal/rescue.rb +11 -9
- data/lib/action_controller/metal/streaming.rb +138 -136
- data/lib/action_controller/metal/strong_parameters.rb +525 -480
- data/lib/action_controller/metal/testing.rb +2 -0
- data/lib/action_controller/metal/url_for.rb +17 -15
- data/lib/action_controller/metal.rb +86 -60
- data/lib/action_controller/railtie.rb +3 -0
- data/lib/action_controller/railties/helpers.rb +2 -0
- data/lib/action_controller/renderer.rb +42 -36
- data/lib/action_controller/template_assertions.rb +4 -2
- data/lib/action_controller/test_case.rb +146 -126
- data/lib/action_controller.rb +10 -3
- data/lib/action_dispatch/constants.rb +2 -0
- data/lib/action_dispatch/deprecator.rb +2 -0
- data/lib/action_dispatch/http/cache.rb +27 -26
- data/lib/action_dispatch/http/content_disposition.rb +2 -0
- data/lib/action_dispatch/http/content_security_policy.rb +44 -38
- data/lib/action_dispatch/http/filter_parameters.rb +18 -9
- data/lib/action_dispatch/http/filter_redirect.rb +22 -1
- data/lib/action_dispatch/http/headers.rb +22 -22
- data/lib/action_dispatch/http/mime_negotiation.rb +30 -41
- data/lib/action_dispatch/http/mime_type.rb +31 -24
- data/lib/action_dispatch/http/mime_types.rb +2 -0
- data/lib/action_dispatch/http/parameters.rb +11 -9
- data/lib/action_dispatch/http/permissions_policy.rb +20 -44
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +94 -75
- data/lib/action_dispatch/http/response.rb +73 -61
- data/lib/action_dispatch/http/upload.rb +18 -16
- data/lib/action_dispatch/http/url.rb +75 -73
- data/lib/action_dispatch/journey/formatter.rb +13 -6
- data/lib/action_dispatch/journey/gtg/builder.rb +4 -3
- data/lib/action_dispatch/journey/gtg/simulator.rb +2 -0
- data/lib/action_dispatch/journey/gtg/transition_table.rb +10 -8
- data/lib/action_dispatch/journey/nfa/dot.rb +2 -0
- data/lib/action_dispatch/journey/nodes/node.rb +6 -5
- data/lib/action_dispatch/journey/parser.rb +4 -3
- data/lib/action_dispatch/journey/parser_extras.rb +2 -0
- data/lib/action_dispatch/journey/path/pattern.rb +4 -1
- data/lib/action_dispatch/journey/route.rb +9 -7
- data/lib/action_dispatch/journey/router/utils.rb +16 -15
- data/lib/action_dispatch/journey/router.rb +4 -2
- data/lib/action_dispatch/journey/routes.rb +4 -2
- data/lib/action_dispatch/journey/scanner.rb +4 -2
- data/lib/action_dispatch/journey/visitors.rb +2 -0
- data/lib/action_dispatch/journey.rb +2 -0
- data/lib/action_dispatch/log_subscriber.rb +2 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +2 -0
- data/lib/action_dispatch/middleware/assume_ssl.rb +8 -5
- data/lib/action_dispatch/middleware/callbacks.rb +3 -1
- data/lib/action_dispatch/middleware/cookies.rb +119 -104
- data/lib/action_dispatch/middleware/debug_exceptions.rb +13 -5
- data/lib/action_dispatch/middleware/debug_locks.rb +15 -13
- data/lib/action_dispatch/middleware/debug_view.rb +2 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +6 -11
- data/lib/action_dispatch/middleware/executor.rb +8 -0
- data/lib/action_dispatch/middleware/flash.rb +63 -51
- data/lib/action_dispatch/middleware/host_authorization.rb +17 -15
- data/lib/action_dispatch/middleware/public_exceptions.rb +8 -6
- data/lib/action_dispatch/middleware/reloader.rb +5 -3
- data/lib/action_dispatch/middleware/remote_ip.rb +77 -72
- data/lib/action_dispatch/middleware/request_id.rb +14 -9
- data/lib/action_dispatch/middleware/server_timing.rb +4 -2
- data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -0
- data/lib/action_dispatch/middleware/session/cache_store.rb +13 -8
- data/lib/action_dispatch/middleware/session/cookie_store.rb +27 -26
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +31 -21
- data/lib/action_dispatch/middleware/ssl.rb +43 -40
- data/lib/action_dispatch/middleware/stack.rb +11 -10
- data/lib/action_dispatch/middleware/static.rb +33 -31
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +1 -1
- data/lib/action_dispatch/railtie.rb +2 -4
- data/lib/action_dispatch/request/session.rb +23 -21
- data/lib/action_dispatch/request/utils.rb +2 -0
- data/lib/action_dispatch/routing/endpoint.rb +2 -0
- data/lib/action_dispatch/routing/inspector.rb +5 -3
- data/lib/action_dispatch/routing/mapper.rb +671 -636
- data/lib/action_dispatch/routing/polymorphic_routes.rb +69 -62
- data/lib/action_dispatch/routing/redirection.rb +37 -32
- data/lib/action_dispatch/routing/route_set.rb +59 -45
- data/lib/action_dispatch/routing/routes_proxy.rb +6 -4
- data/lib/action_dispatch/routing/url_for.rb +130 -125
- data/lib/action_dispatch/routing.rb +150 -148
- data/lib/action_dispatch/system_test_case.rb +91 -81
- data/lib/action_dispatch/system_testing/browser.rb +10 -3
- data/lib/action_dispatch/system_testing/driver.rb +3 -1
- data/lib/action_dispatch/system_testing/server.rb +2 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +32 -21
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
- data/lib/action_dispatch/testing/assertion_response.rb +8 -6
- data/lib/action_dispatch/testing/assertions/response.rb +26 -23
- data/lib/action_dispatch/testing/assertions/routing.rb +153 -84
- data/lib/action_dispatch/testing/assertions.rb +2 -0
- data/lib/action_dispatch/testing/integration.rb +223 -222
- data/lib/action_dispatch/testing/request_encoder.rb +2 -0
- data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
- data/lib/action_dispatch/testing/test_process.rb +12 -8
- data/lib/action_dispatch/testing/test_request.rb +3 -1
- data/lib/action_dispatch/testing/test_response.rb +27 -26
- data/lib/action_dispatch.rb +22 -28
- data/lib/action_pack/gem_version.rb +6 -4
- data/lib/action_pack/version.rb +3 -1
- data/lib/action_pack.rb +17 -16
- metadata +39 -16
@@ -1,32 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# :markup: markdown
|
4
|
+
|
3
5
|
module AbstractController
|
4
|
-
#
|
5
|
-
#
|
6
|
-
# Abstract Controller provides hooks during the life cycle of a controller action.
|
7
|
-
# Callbacks allow you to trigger logic during this cycle. Available callbacks are:
|
8
|
-
#
|
9
|
-
# * <tt>after_action</tt>
|
10
|
-
# * <tt>append_after_action</tt>
|
11
|
-
# * <tt>append_around_action</tt>
|
12
|
-
# * <tt>append_before_action</tt>
|
13
|
-
# * <tt>around_action</tt>
|
14
|
-
# * <tt>before_action</tt>
|
15
|
-
# * <tt>prepend_after_action</tt>
|
16
|
-
# * <tt>prepend_around_action</tt>
|
17
|
-
# * <tt>prepend_before_action</tt>
|
18
|
-
# * <tt>skip_after_action</tt>
|
19
|
-
# * <tt>skip_around_action</tt>
|
20
|
-
# * <tt>skip_before_action</tt>
|
6
|
+
# # Abstract Controller Callbacks
|
21
7
|
#
|
22
|
-
#
|
8
|
+
# Abstract Controller provides hooks during the life cycle of a controller
|
9
|
+
# action. Callbacks allow you to trigger logic during this cycle. Available
|
10
|
+
# callbacks are:
|
23
11
|
#
|
12
|
+
# * `after_action`
|
13
|
+
# * `append_after_action`
|
14
|
+
# * `append_around_action`
|
15
|
+
# * `append_before_action`
|
16
|
+
# * `around_action`
|
17
|
+
# * `before_action`
|
18
|
+
# * `prepend_after_action`
|
19
|
+
# * `prepend_around_action`
|
20
|
+
# * `prepend_before_action`
|
21
|
+
# * `skip_after_action`
|
22
|
+
# * `skip_around_action`
|
23
|
+
# * `skip_before_action`
|
24
24
|
module Callbacks
|
25
25
|
extend ActiveSupport::Concern
|
26
26
|
|
27
|
-
# Uses ActiveSupport::Callbacks as the base functionality. For
|
28
|
-
#
|
29
|
-
#
|
27
|
+
# Uses ActiveSupport::Callbacks as the base functionality. For more details on
|
28
|
+
# the whole callback system, read the documentation for
|
29
|
+
# ActiveSupport::Callbacks.
|
30
30
|
include ActiveSupport::Callbacks
|
31
31
|
|
32
32
|
included do
|
@@ -72,25 +72,24 @@ module AbstractController
|
|
72
72
|
end
|
73
73
|
|
74
74
|
module ClassMethods
|
75
|
-
# If
|
76
|
-
#
|
75
|
+
# If `:only` or `:except` are used, convert the options into the `:if` and
|
76
|
+
# `:unless` options of ActiveSupport::Callbacks.
|
77
77
|
#
|
78
|
-
# The basic idea is that
|
79
|
-
#
|
78
|
+
# The basic idea is that `:only => :index` gets converted to `:if => proc {|c|
|
79
|
+
# c.action_name == "index" }`.
|
80
80
|
#
|
81
|
-
# Note that
|
82
|
-
# are used together.
|
81
|
+
# Note that `:only` has priority over `:if` in case they are used together.
|
83
82
|
#
|
84
|
-
#
|
83
|
+
# only: :index, if: -> { true } # the :if option will be ignored.
|
85
84
|
#
|
86
|
-
# Note that
|
87
|
-
# are used together.
|
85
|
+
# Note that `:if` has priority over `:except` in case they are used together.
|
88
86
|
#
|
89
|
-
#
|
87
|
+
# except: :index, if: -> { true } # the :except option will be ignored.
|
88
|
+
#
|
89
|
+
# #### Options
|
90
|
+
# * `only` - The callback should be run only for this action.
|
91
|
+
# * `except` - The callback should be run for all actions except this action.
|
90
92
|
#
|
91
|
-
# ==== Options
|
92
|
-
# * <tt>only</tt> - The callback should be run only for this action.
|
93
|
-
# * <tt>except</tt> - The callback should be run for all actions except this action.
|
94
93
|
def _normalize_callback_options(options)
|
95
94
|
_normalize_callback_option(options, :only, :if)
|
96
95
|
_normalize_callback_option(options, :except, :unless)
|
@@ -104,18 +103,20 @@ module AbstractController
|
|
104
103
|
end
|
105
104
|
end
|
106
105
|
|
107
|
-
# Take callback names and an optional callback proc, normalize them,
|
108
|
-
#
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
# *
|
113
|
-
#
|
114
|
-
# *
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
# *
|
106
|
+
# Take callback names and an optional callback proc, normalize them, then call
|
107
|
+
# the block with each callback. This allows us to abstract the normalization
|
108
|
+
# across several methods that use it.
|
109
|
+
#
|
110
|
+
# #### Parameters
|
111
|
+
# * `callbacks` - An array of callbacks, with an optional options hash as the
|
112
|
+
# last parameter.
|
113
|
+
# * `block` - A proc that should be added to the callbacks.
|
114
|
+
#
|
115
|
+
#
|
116
|
+
# #### Block Parameters
|
117
|
+
# * `name` - The callback to be added.
|
118
|
+
# * `options` - A hash of options to be used when adding the callback.
|
119
|
+
#
|
119
120
|
def _insert_callbacks(callbacks, block = nil)
|
120
121
|
options = callbacks.extract_options!
|
121
122
|
callbacks.push(block) if block
|
@@ -134,20 +135,21 @@ module AbstractController
|
|
134
135
|
#
|
135
136
|
# Append a callback before actions. See _insert_callbacks for parameter details.
|
136
137
|
#
|
137
|
-
# If the callback renders or redirects, the action will not run. If there
|
138
|
-
#
|
139
|
-
#
|
138
|
+
# If the callback renders or redirects, the action will not run. If there are
|
139
|
+
# additional callbacks scheduled to run after that callback, they are also
|
140
|
+
# cancelled.
|
140
141
|
|
141
142
|
##
|
142
143
|
# :method: prepend_before_action
|
143
144
|
#
|
144
145
|
# :call-seq: prepend_before_action(names, block)
|
145
146
|
#
|
146
|
-
# Prepend a callback before actions. See _insert_callbacks for parameter
|
147
|
+
# Prepend a callback before actions. See _insert_callbacks for parameter
|
148
|
+
# details.
|
147
149
|
#
|
148
|
-
# If the callback renders or redirects, the action will not run. If there
|
149
|
-
#
|
150
|
-
#
|
150
|
+
# If the callback renders or redirects, the action will not run. If there are
|
151
|
+
# additional callbacks scheduled to run after that callback, they are also
|
152
|
+
# cancelled.
|
151
153
|
|
152
154
|
##
|
153
155
|
# :method: skip_before_action
|
@@ -163,9 +165,9 @@ module AbstractController
|
|
163
165
|
#
|
164
166
|
# Append a callback before actions. See _insert_callbacks for parameter details.
|
165
167
|
#
|
166
|
-
# If the callback renders or redirects, the action will not run. If there
|
167
|
-
#
|
168
|
-
#
|
168
|
+
# If the callback renders or redirects, the action will not run. If there are
|
169
|
+
# additional callbacks scheduled to run after that callback, they are also
|
170
|
+
# cancelled.
|
169
171
|
|
170
172
|
##
|
171
173
|
# :method: after_action
|
@@ -207,7 +209,8 @@ module AbstractController
|
|
207
209
|
#
|
208
210
|
# :call-seq: prepend_around_action(names, block)
|
209
211
|
#
|
210
|
-
# Prepend a callback around actions. See _insert_callbacks for parameter
|
212
|
+
# Prepend a callback around actions. See _insert_callbacks for parameter
|
213
|
+
# details.
|
211
214
|
|
212
215
|
##
|
213
216
|
# :method: skip_around_action
|
@@ -222,9 +225,8 @@ module AbstractController
|
|
222
225
|
# :call-seq: append_around_action(names, block)
|
223
226
|
#
|
224
227
|
# Append a callback around actions. See _insert_callbacks for parameter details.
|
225
|
-
|
226
|
-
#
|
227
|
-
# for each of before, after, and around.
|
228
|
+
# set up before_action, prepend_before_action, skip_before_action, etc. for each
|
229
|
+
# of before, after, and around.
|
228
230
|
[:before, :after, :around].each do |callback|
|
229
231
|
define_method "#{callback}_action" do |*names, &blk|
|
230
232
|
_insert_callbacks(names, blk) do |name, options|
|
@@ -238,8 +240,8 @@ module AbstractController
|
|
238
240
|
end
|
239
241
|
end
|
240
242
|
|
241
|
-
# Skip a before, after or around callback. See _insert_callbacks
|
242
|
-
#
|
243
|
+
# Skip a before, after or around callback. See _insert_callbacks for details on
|
244
|
+
# the allowed parameters.
|
243
245
|
define_method "skip_#{callback}_action" do |*names|
|
244
246
|
_insert_callbacks(names) do |name, options|
|
245
247
|
skip_callback(:process_action, callback, name, options)
|
@@ -252,8 +254,8 @@ module AbstractController
|
|
252
254
|
end
|
253
255
|
|
254
256
|
private
|
255
|
-
# Override
|
256
|
-
#
|
257
|
+
# Override `AbstractController::Base#process_action` to run the `process_action`
|
258
|
+
# callbacks around the normal behavior.
|
257
259
|
def process_action(...)
|
258
260
|
run_callbacks(:process_action) do
|
259
261
|
super
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# :markup: markdown
|
4
|
+
|
3
5
|
require "action_dispatch/http/mime_type"
|
4
6
|
|
5
7
|
module AbstractController
|
@@ -7,10 +9,9 @@ module AbstractController
|
|
7
9
|
def self.generate_method_for_mime(mime)
|
8
10
|
sym = mime.is_a?(Symbol) ? mime : mime.to_sym
|
9
11
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
10
|
-
def #{sym}(
|
11
|
-
custom(Mime[:#{sym}],
|
12
|
+
def #{sym}(...)
|
13
|
+
custom(Mime[:#{sym}], ...)
|
12
14
|
end
|
13
|
-
ruby2_keywords(:#{sym})
|
14
15
|
RUBY
|
15
16
|
end
|
16
17
|
|
@@ -23,7 +24,7 @@ module AbstractController
|
|
23
24
|
end
|
24
25
|
|
25
26
|
private
|
26
|
-
def method_missing(symbol,
|
27
|
+
def method_missing(symbol, ...)
|
27
28
|
unless mime_constant = Mime[symbol]
|
28
29
|
raise NoMethodError, "To respond to a custom format, register it as a MIME type first: " \
|
29
30
|
"https://guides.rubyonrails.org/action_controller_overview.html#restful-downloads. " \
|
@@ -34,11 +35,10 @@ module AbstractController
|
|
34
35
|
|
35
36
|
if Mime::SET.include?(mime_constant)
|
36
37
|
AbstractController::Collector.generate_method_for_mime(mime_constant)
|
37
|
-
public_send(symbol,
|
38
|
+
public_send(symbol, ...)
|
38
39
|
else
|
39
40
|
super
|
40
41
|
end
|
41
42
|
end
|
42
|
-
ruby2_keywords(:method_missing)
|
43
43
|
end
|
44
44
|
end
|
@@ -1,18 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# :markup: markdown
|
4
|
+
|
3
5
|
require "active_support/dependencies"
|
4
6
|
require "active_support/core_ext/name_error"
|
5
7
|
|
6
8
|
module AbstractController
|
7
9
|
module Helpers
|
8
|
-
include ActiveSupport::Deprecation::DeprecatedConstantAccessor
|
9
10
|
extend ActiveSupport::Concern
|
10
11
|
|
11
12
|
included do
|
12
13
|
class_attribute :_helper_methods, default: Array.new
|
13
14
|
|
14
|
-
# This is here so that it is always higher in the inheritance chain than
|
15
|
-
#
|
15
|
+
# This is here so that it is always higher in the inheritance chain than the
|
16
|
+
# definition in lib/action_view/rendering.rb
|
16
17
|
redefine_singleton_method(:_helpers) do
|
17
18
|
if @_helpers ||= nil
|
18
19
|
@_helpers
|
@@ -24,23 +25,6 @@ module AbstractController
|
|
24
25
|
self._helpers = define_helpers_module(self)
|
25
26
|
end
|
26
27
|
|
27
|
-
class DeprecatedMissingHelperError < LoadError
|
28
|
-
def initialize(error, path)
|
29
|
-
@error = error
|
30
|
-
@path = "helpers/#{path}.rb"
|
31
|
-
set_backtrace error.backtrace
|
32
|
-
|
33
|
-
if /^#{path}(\.rb)?$/.match?(error.path)
|
34
|
-
super("Missing helper file helpers/%s.rb" % path)
|
35
|
-
else
|
36
|
-
raise error
|
37
|
-
end
|
38
|
-
end
|
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
|
43
|
-
|
44
28
|
def _helpers
|
45
29
|
self.class._helpers
|
46
30
|
end
|
@@ -78,9 +62,9 @@ module AbstractController
|
|
78
62
|
extend Resolution
|
79
63
|
|
80
64
|
module ClassMethods
|
81
|
-
# When a class is inherited, wrap its helper module in a new module.
|
82
|
-
#
|
83
|
-
#
|
65
|
+
# When a class is inherited, wrap its helper module in a new module. This
|
66
|
+
# ensures that the parent class's module can be changed independently of the
|
67
|
+
# child class's.
|
84
68
|
def inherited(klass)
|
85
69
|
# Inherited from parent by default
|
86
70
|
klass._helpers = nil
|
@@ -97,46 +81,48 @@ module AbstractController
|
|
97
81
|
# :method: modules_for_helpers
|
98
82
|
# :call-seq: modules_for_helpers(modules_or_helper_prefixes)
|
99
83
|
#
|
100
|
-
# Given an array of values like the ones accepted by
|
84
|
+
# Given an array of values like the ones accepted by `helper`, this method
|
101
85
|
# returns an array with the corresponding modules, in the same order.
|
102
86
|
#
|
87
|
+
# ActionController::Base.modules_for_helpers(["application", "chart", "rubygems"])
|
88
|
+
# # => [ApplicationHelper, ChartHelper, RubygemsHelper]
|
89
|
+
#
|
103
90
|
#--
|
104
91
|
# Implemented by Resolution#modules_for_helpers.
|
105
92
|
|
106
|
-
|
107
|
-
# :method: all_helpers_from_path
|
93
|
+
# :method: # all_helpers_from_path
|
108
94
|
# :call-seq: all_helpers_from_path(path)
|
109
95
|
#
|
110
96
|
# Returns a list of helper names in a given path.
|
111
97
|
#
|
112
|
-
#
|
113
|
-
#
|
98
|
+
# ActionController::Base.all_helpers_from_path 'app/helpers'
|
99
|
+
# # => ["application", "chart", "rubygems"]
|
114
100
|
#
|
115
101
|
#--
|
116
102
|
# Implemented by Resolution#all_helpers_from_path.
|
117
103
|
|
118
104
|
# Declare a controller method as a helper. For example, the following
|
119
|
-
# makes the
|
105
|
+
# makes the `current_user` and `logged_in?` controller methods available
|
120
106
|
# to the view:
|
121
|
-
#
|
122
|
-
#
|
107
|
+
# class ApplicationController < ActionController::Base
|
108
|
+
# helper_method :current_user, :logged_in?
|
123
109
|
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
110
|
+
# private
|
111
|
+
# def current_user
|
112
|
+
# @current_user ||= User.find_by(id: session[:user])
|
113
|
+
# end
|
128
114
|
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
115
|
+
# def logged_in?
|
116
|
+
# current_user != nil
|
117
|
+
# end
|
118
|
+
# end
|
133
119
|
#
|
134
120
|
# In a view:
|
135
|
-
#
|
121
|
+
# <% if logged_in? -%>Welcome, <%= current_user.name %><% end -%>
|
136
122
|
#
|
137
|
-
#
|
138
|
-
# *
|
139
|
-
#
|
123
|
+
# #### Parameters
|
124
|
+
# * `method[, method]` - A name or names of a method on the controller to be
|
125
|
+
# made available on the view.
|
140
126
|
def helper_method(*methods)
|
141
127
|
methods.flatten!
|
142
128
|
self._helper_methods += methods
|
@@ -145,68 +131,67 @@ module AbstractController
|
|
145
131
|
file, line = location.path, location.lineno
|
146
132
|
|
147
133
|
methods.each do |method|
|
148
|
-
# def current_user(
|
149
|
-
# controller.send(:'current_user',
|
134
|
+
# def current_user(...)
|
135
|
+
# controller.send(:'current_user', ...)
|
150
136
|
# end
|
151
137
|
_helpers_for_modification.class_eval <<~ruby_eval.lines.map(&:strip).join(";"), file, line
|
152
|
-
def #{method}(
|
153
|
-
controller.send(:'#{method}',
|
138
|
+
def #{method}(...)
|
139
|
+
controller.send(:'#{method}', ...)
|
154
140
|
end
|
155
|
-
ruby2_keywords(:'#{method}')
|
156
141
|
ruby_eval
|
157
142
|
end
|
158
143
|
end
|
159
144
|
|
160
145
|
# Includes the given modules in the template class.
|
161
146
|
#
|
162
|
-
# Modules can be specified in different ways. All of the following calls
|
163
|
-
#
|
147
|
+
# Modules can be specified in different ways. All of the following calls include
|
148
|
+
# `FooHelper`:
|
164
149
|
#
|
165
|
-
#
|
166
|
-
#
|
150
|
+
# # Module, recommended.
|
151
|
+
# helper FooHelper
|
167
152
|
#
|
168
|
-
#
|
169
|
-
#
|
170
|
-
#
|
171
|
-
#
|
172
|
-
#
|
153
|
+
# # String/symbol without the "helper" suffix, camel or snake case.
|
154
|
+
# helper "Foo"
|
155
|
+
# helper :Foo
|
156
|
+
# helper "foo"
|
157
|
+
# helper :foo
|
173
158
|
#
|
174
|
-
# The last two assume that
|
159
|
+
# The last two assume that `"foo".camelize` returns "Foo".
|
175
160
|
#
|
176
|
-
# When strings or symbols are passed, the method finds the actual module
|
177
|
-
#
|
178
|
-
#
|
161
|
+
# When strings or symbols are passed, the method finds the actual module object
|
162
|
+
# using String#constantize. Therefore, if the module has not been yet loaded, it
|
163
|
+
# has to be autoloadable, which is normally the case.
|
179
164
|
#
|
180
|
-
# Namespaces are supported. The following calls include
|
165
|
+
# Namespaces are supported. The following calls include `Foo::BarHelper`:
|
181
166
|
#
|
182
|
-
#
|
183
|
-
#
|
167
|
+
# # Module, recommended.
|
168
|
+
# helper Foo::BarHelper
|
184
169
|
#
|
185
|
-
#
|
186
|
-
#
|
187
|
-
#
|
188
|
-
#
|
189
|
-
#
|
170
|
+
# # String/symbol without the "helper" suffix, camel or snake case.
|
171
|
+
# helper "Foo::Bar"
|
172
|
+
# helper :"Foo::Bar"
|
173
|
+
# helper "foo/bar"
|
174
|
+
# helper :"foo/bar"
|
190
175
|
#
|
191
|
-
# The last two assume that
|
176
|
+
# The last two assume that `"foo/bar".camelize` returns "Foo::Bar".
|
192
177
|
#
|
193
|
-
# The method accepts a block too. If present, the block is evaluated in
|
194
|
-
#
|
195
|
-
#
|
178
|
+
# The method accepts a block too. If present, the block is evaluated in the
|
179
|
+
# context of the controller helper module. This simple call makes the `wadus`
|
180
|
+
# method available in templates of the enclosing controller:
|
196
181
|
#
|
197
|
-
#
|
198
|
-
#
|
199
|
-
#
|
182
|
+
# helper do
|
183
|
+
# def wadus
|
184
|
+
# "wadus"
|
185
|
+
# end
|
200
186
|
# end
|
201
|
-
# end
|
202
187
|
#
|
203
188
|
# Furthermore, all the above styles can be mixed together:
|
204
189
|
#
|
205
|
-
#
|
206
|
-
#
|
207
|
-
#
|
190
|
+
# helper FooHelper, "woo", "bar/baz" do
|
191
|
+
# def wadus
|
192
|
+
# "wadus"
|
193
|
+
# end
|
208
194
|
# end
|
209
|
-
# end
|
210
195
|
#
|
211
196
|
def helper(*args, &block)
|
212
197
|
modules_for_helpers(args).each do |mod|
|
@@ -217,8 +202,8 @@ module AbstractController
|
|
217
202
|
_helpers_for_modification.module_eval(&block) if block_given?
|
218
203
|
end
|
219
204
|
|
220
|
-
# Clears up all existing helpers in this class, only keeping the helper
|
221
|
-
#
|
205
|
+
# Clears up all existing helpers in this class, only keeping the helper with the
|
206
|
+
# same name as this class.
|
222
207
|
def clear_helpers
|
223
208
|
inherited_helper_methods = _helper_methods
|
224
209
|
self._helpers = Module.new
|
@@ -237,8 +222,8 @@ module AbstractController
|
|
237
222
|
|
238
223
|
private
|
239
224
|
def define_helpers_module(klass, helpers = nil)
|
240
|
-
# In some tests inherited is called explicitly. In that case, just
|
241
|
-
#
|
225
|
+
# In some tests inherited is called explicitly. In that case, just return the
|
226
|
+
# module from the first time it was defined
|
242
227
|
return klass.const_get(:HelperMethods) if klass.const_defined?(:HelperMethods, false)
|
243
228
|
|
244
229
|
mod = Module.new
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# :markup: markdown
|
4
|
+
|
3
5
|
require "abstract_controller/error"
|
4
6
|
require "action_view"
|
5
7
|
require "action_view/view_paths"
|
@@ -19,9 +21,9 @@ module AbstractController
|
|
19
21
|
include ActionView::ViewPaths
|
20
22
|
|
21
23
|
# Normalizes arguments and options, and then delegates to render_to_body and
|
22
|
-
# sticks the result in
|
24
|
+
# sticks the result in `self.response_body`.
|
23
25
|
#
|
24
|
-
# Supported options depend on the underlying
|
26
|
+
# Supported options depend on the underlying `render_to_body` implementation.
|
25
27
|
def render(*args, &block)
|
26
28
|
options = _normalize_render(*args, &block)
|
27
29
|
rendered_body = render_to_body(options)
|
@@ -35,11 +37,11 @@ module AbstractController
|
|
35
37
|
end
|
36
38
|
|
37
39
|
# Similar to #render, but only returns the rendered template as a string,
|
38
|
-
# instead of setting
|
40
|
+
# instead of setting `self.response_body`.
|
39
41
|
#
|
40
|
-
# If a component extends the semantics of
|
41
|
-
# extends it to be anything that responds to the method each), this method
|
42
|
-
#
|
42
|
+
# If a component extends the semantics of `response_body` (as ActionController
|
43
|
+
# extends it to be anything that responds to the method each), this method needs
|
44
|
+
# to be overridden in order to still return a string.
|
43
45
|
def render_to_string(*args, &block)
|
44
46
|
options = _normalize_render(*args, &block)
|
45
47
|
render_to_body(options)
|
@@ -49,15 +51,15 @@ module AbstractController
|
|
49
51
|
def render_to_body(options = {})
|
50
52
|
end
|
51
53
|
|
52
|
-
# Returns
|
54
|
+
# Returns `Content-Type` of rendered content.
|
53
55
|
def rendered_format
|
54
56
|
Mime[:text]
|
55
57
|
end
|
56
58
|
|
57
59
|
DEFAULT_PROTECTED_INSTANCE_VARIABLES = %i(@_action_name @_response_body @_formats @_prefixes)
|
58
60
|
|
59
|
-
# This method should return a hash with assigns.
|
60
|
-
#
|
61
|
+
# This method should return a hash with assigns. You can overwrite this
|
62
|
+
# configuration per controller.
|
61
63
|
def view_assigns
|
62
64
|
variables = instance_variables - _protected_ivars
|
63
65
|
|
@@ -67,9 +69,8 @@ module AbstractController
|
|
67
69
|
end
|
68
70
|
|
69
71
|
private
|
70
|
-
# Normalize args by converting
|
71
|
-
#
|
72
|
-
# <tt>render file: "foo/bar"</tt>.
|
72
|
+
# Normalize args by converting `render "foo"` to `render action: "foo"` and
|
73
|
+
# `render "foo/bar"` to `render file: "foo/bar"`.
|
73
74
|
def _normalize_args(action = nil, options = {}) # :doc:
|
74
75
|
if action.respond_to?(:permitted?)
|
75
76
|
if action.permitted?
|
@@ -1,17 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# :markup: markdown
|
4
|
+
|
3
5
|
require "active_support/html_safe_translation"
|
4
6
|
|
5
7
|
module AbstractController
|
6
8
|
module Translation
|
7
|
-
# Delegates to
|
9
|
+
# Delegates to `I18n.translate`.
|
8
10
|
#
|
9
11
|
# When the given key starts with a period, it will be scoped by the current
|
10
|
-
# controller and action. So if you call
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
12
|
+
# controller and action. So if you call `translate(".foo")` from
|
13
|
+
# `PeopleController#index`, it will convert the call to
|
14
|
+
# `I18n.translate("people.index.foo")`. This makes it less repetitive to
|
15
|
+
# translate many keys within the same controller / action and gives you a simple
|
16
|
+
# framework for scoping them consistently.
|
15
17
|
def translate(key, **options)
|
16
18
|
if key&.start_with?(".")
|
17
19
|
path = controller_path.tr("/", ".")
|
@@ -21,11 +23,17 @@ module AbstractController
|
|
21
23
|
key = "#{path}.#{action_name}#{key}"
|
22
24
|
end
|
23
25
|
|
26
|
+
if options[:default] && ActiveSupport::HtmlSafeTranslation.html_safe_translation_key?(key)
|
27
|
+
options[:default] = Array(options[:default]).map do |value|
|
28
|
+
value.is_a?(String) ? ERB::Util.html_escape(value) : value
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
24
32
|
ActiveSupport::HtmlSafeTranslation.translate(key, **options)
|
25
33
|
end
|
26
34
|
alias :t :translate
|
27
35
|
|
28
|
-
# Delegates to
|
36
|
+
# Delegates to `I18n.localize`.
|
29
37
|
def localize(object, **options)
|
30
38
|
I18n.localize(object, **options)
|
31
39
|
end
|