omg-actionpack 8.0.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +129 -0
- data/MIT-LICENSE +21 -0
- data/README.rdoc +57 -0
- data/lib/abstract_controller/asset_paths.rb +14 -0
- data/lib/abstract_controller/base.rb +299 -0
- data/lib/abstract_controller/caching/fragments.rb +149 -0
- data/lib/abstract_controller/caching.rb +68 -0
- data/lib/abstract_controller/callbacks.rb +265 -0
- data/lib/abstract_controller/collector.rb +44 -0
- data/lib/abstract_controller/deprecator.rb +9 -0
- data/lib/abstract_controller/error.rb +8 -0
- data/lib/abstract_controller/helpers.rb +243 -0
- data/lib/abstract_controller/logger.rb +16 -0
- data/lib/abstract_controller/railties/routes_helpers.rb +25 -0
- data/lib/abstract_controller/rendering.rb +126 -0
- data/lib/abstract_controller/translation.rb +42 -0
- data/lib/abstract_controller/url_for.rb +37 -0
- data/lib/abstract_controller.rb +36 -0
- data/lib/action_controller/api/api_rendering.rb +18 -0
- data/lib/action_controller/api.rb +155 -0
- data/lib/action_controller/base.rb +332 -0
- data/lib/action_controller/caching.rb +49 -0
- data/lib/action_controller/deprecator.rb +9 -0
- data/lib/action_controller/form_builder.rb +55 -0
- data/lib/action_controller/log_subscriber.rb +96 -0
- data/lib/action_controller/metal/allow_browser.rb +123 -0
- data/lib/action_controller/metal/basic_implicit_render.rb +17 -0
- data/lib/action_controller/metal/conditional_get.rb +341 -0
- data/lib/action_controller/metal/content_security_policy.rb +86 -0
- data/lib/action_controller/metal/cookies.rb +20 -0
- data/lib/action_controller/metal/data_streaming.rb +154 -0
- data/lib/action_controller/metal/default_headers.rb +21 -0
- data/lib/action_controller/metal/etag_with_flash.rb +22 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +59 -0
- data/lib/action_controller/metal/exceptions.rb +106 -0
- data/lib/action_controller/metal/flash.rb +67 -0
- data/lib/action_controller/metal/head.rb +67 -0
- data/lib/action_controller/metal/helpers.rb +129 -0
- data/lib/action_controller/metal/http_authentication.rb +565 -0
- data/lib/action_controller/metal/implicit_render.rb +67 -0
- data/lib/action_controller/metal/instrumentation.rb +120 -0
- data/lib/action_controller/metal/live.rb +398 -0
- data/lib/action_controller/metal/logging.rb +22 -0
- data/lib/action_controller/metal/mime_responds.rb +337 -0
- data/lib/action_controller/metal/parameter_encoding.rb +84 -0
- data/lib/action_controller/metal/params_wrapper.rb +312 -0
- data/lib/action_controller/metal/permissions_policy.rb +38 -0
- data/lib/action_controller/metal/rate_limiting.rb +62 -0
- data/lib/action_controller/metal/redirecting.rb +251 -0
- data/lib/action_controller/metal/renderers.rb +181 -0
- data/lib/action_controller/metal/rendering.rb +260 -0
- data/lib/action_controller/metal/request_forgery_protection.rb +667 -0
- data/lib/action_controller/metal/rescue.rb +33 -0
- data/lib/action_controller/metal/streaming.rb +183 -0
- data/lib/action_controller/metal/strong_parameters.rb +1546 -0
- data/lib/action_controller/metal/testing.rb +25 -0
- data/lib/action_controller/metal/url_for.rb +65 -0
- data/lib/action_controller/metal.rb +339 -0
- data/lib/action_controller/railtie.rb +149 -0
- data/lib/action_controller/railties/helpers.rb +26 -0
- data/lib/action_controller/renderer.rb +161 -0
- data/lib/action_controller/template_assertions.rb +13 -0
- data/lib/action_controller/test_case.rb +691 -0
- data/lib/action_controller.rb +80 -0
- data/lib/action_dispatch/constants.rb +34 -0
- data/lib/action_dispatch/deprecator.rb +9 -0
- data/lib/action_dispatch/http/cache.rb +249 -0
- data/lib/action_dispatch/http/content_disposition.rb +47 -0
- data/lib/action_dispatch/http/content_security_policy.rb +365 -0
- data/lib/action_dispatch/http/filter_parameters.rb +80 -0
- data/lib/action_dispatch/http/filter_redirect.rb +50 -0
- data/lib/action_dispatch/http/headers.rb +134 -0
- data/lib/action_dispatch/http/mime_negotiation.rb +187 -0
- data/lib/action_dispatch/http/mime_type.rb +389 -0
- data/lib/action_dispatch/http/mime_types.rb +54 -0
- data/lib/action_dispatch/http/parameters.rb +119 -0
- data/lib/action_dispatch/http/permissions_policy.rb +189 -0
- data/lib/action_dispatch/http/rack_cache.rb +67 -0
- data/lib/action_dispatch/http/request.rb +498 -0
- data/lib/action_dispatch/http/response.rb +556 -0
- data/lib/action_dispatch/http/upload.rb +107 -0
- data/lib/action_dispatch/http/url.rb +344 -0
- data/lib/action_dispatch/journey/formatter.rb +226 -0
- data/lib/action_dispatch/journey/gtg/builder.rb +149 -0
- data/lib/action_dispatch/journey/gtg/simulator.rb +50 -0
- data/lib/action_dispatch/journey/gtg/transition_table.rb +217 -0
- data/lib/action_dispatch/journey/nfa/dot.rb +27 -0
- data/lib/action_dispatch/journey/nodes/node.rb +208 -0
- data/lib/action_dispatch/journey/parser.rb +103 -0
- data/lib/action_dispatch/journey/path/pattern.rb +209 -0
- data/lib/action_dispatch/journey/route.rb +189 -0
- data/lib/action_dispatch/journey/router/utils.rb +105 -0
- data/lib/action_dispatch/journey/router.rb +151 -0
- data/lib/action_dispatch/journey/routes.rb +82 -0
- data/lib/action_dispatch/journey/scanner.rb +70 -0
- data/lib/action_dispatch/journey/visitors.rb +267 -0
- data/lib/action_dispatch/journey/visualizer/fsm.css +30 -0
- data/lib/action_dispatch/journey/visualizer/fsm.js +159 -0
- data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
- data/lib/action_dispatch/journey.rb +7 -0
- data/lib/action_dispatch/log_subscriber.rb +25 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
- data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
- data/lib/action_dispatch/middleware/callbacks.rb +38 -0
- data/lib/action_dispatch/middleware/cookies.rb +719 -0
- data/lib/action_dispatch/middleware/debug_exceptions.rb +206 -0
- data/lib/action_dispatch/middleware/debug_locks.rb +129 -0
- data/lib/action_dispatch/middleware/debug_view.rb +73 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +350 -0
- data/lib/action_dispatch/middleware/executor.rb +32 -0
- data/lib/action_dispatch/middleware/flash.rb +318 -0
- data/lib/action_dispatch/middleware/host_authorization.rb +171 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +64 -0
- data/lib/action_dispatch/middleware/reloader.rb +16 -0
- data/lib/action_dispatch/middleware/remote_ip.rb +199 -0
- data/lib/action_dispatch/middleware/request_id.rb +50 -0
- data/lib/action_dispatch/middleware/server_timing.rb +78 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +112 -0
- data/lib/action_dispatch/middleware/session/cache_store.rb +66 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +129 -0
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +34 -0
- data/lib/action_dispatch/middleware/show_exceptions.rb +88 -0
- data/lib/action_dispatch/middleware/ssl.rb +180 -0
- data/lib/action_dispatch/middleware/stack.rb +194 -0
- data/lib/action_dispatch/middleware/static.rb +192 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +17 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +36 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +62 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +12 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +35 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +16 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +284 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +32 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +6 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +19 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +232 -0
- data/lib/action_dispatch/railtie.rb +77 -0
- data/lib/action_dispatch/request/session.rb +283 -0
- data/lib/action_dispatch/request/utils.rb +109 -0
- data/lib/action_dispatch/routing/endpoint.rb +19 -0
- data/lib/action_dispatch/routing/inspector.rb +323 -0
- data/lib/action_dispatch/routing/mapper.rb +2372 -0
- data/lib/action_dispatch/routing/polymorphic_routes.rb +363 -0
- data/lib/action_dispatch/routing/redirection.rb +218 -0
- data/lib/action_dispatch/routing/route_set.rb +958 -0
- data/lib/action_dispatch/routing/routes_proxy.rb +66 -0
- data/lib/action_dispatch/routing/url_for.rb +244 -0
- data/lib/action_dispatch/routing.rb +262 -0
- data/lib/action_dispatch/system_test_case.rb +206 -0
- data/lib/action_dispatch/system_testing/browser.rb +75 -0
- data/lib/action_dispatch/system_testing/driver.rb +85 -0
- data/lib/action_dispatch/system_testing/server.rb +33 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +164 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +23 -0
- data/lib/action_dispatch/testing/assertion_response.rb +48 -0
- data/lib/action_dispatch/testing/assertions/response.rb +114 -0
- data/lib/action_dispatch/testing/assertions/routing.rb +343 -0
- data/lib/action_dispatch/testing/assertions.rb +25 -0
- data/lib/action_dispatch/testing/integration.rb +694 -0
- data/lib/action_dispatch/testing/request_encoder.rb +60 -0
- data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
- data/lib/action_dispatch/testing/test_process.rb +57 -0
- data/lib/action_dispatch/testing/test_request.rb +73 -0
- data/lib/action_dispatch/testing/test_response.rb +58 -0
- data/lib/action_dispatch.rb +147 -0
- data/lib/action_pack/gem_version.rb +19 -0
- data/lib/action_pack/version.rb +12 -0
- data/lib/action_pack.rb +27 -0
- metadata +375 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
module AbstractController
|
6
|
+
module Caching
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
extend ActiveSupport::Autoload
|
9
|
+
|
10
|
+
eager_autoload do
|
11
|
+
autoload :Fragments
|
12
|
+
end
|
13
|
+
|
14
|
+
module ConfigMethods
|
15
|
+
def cache_store
|
16
|
+
config.cache_store
|
17
|
+
end
|
18
|
+
|
19
|
+
def cache_store=(store)
|
20
|
+
config.cache_store = ActiveSupport::Cache.lookup_store(*store)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def cache_configured?
|
25
|
+
perform_caching && cache_store
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
include ConfigMethods
|
30
|
+
include AbstractController::Caching::Fragments
|
31
|
+
|
32
|
+
included do
|
33
|
+
extend ConfigMethods
|
34
|
+
|
35
|
+
config_accessor :default_static_extension
|
36
|
+
self.default_static_extension ||= ".html"
|
37
|
+
|
38
|
+
config_accessor :perform_caching
|
39
|
+
self.perform_caching = true if perform_caching.nil?
|
40
|
+
|
41
|
+
config_accessor :enable_fragment_cache_logging
|
42
|
+
self.enable_fragment_cache_logging = false
|
43
|
+
|
44
|
+
class_attribute :_view_cache_dependencies, default: []
|
45
|
+
helper_method :view_cache_dependencies if respond_to?(:helper_method)
|
46
|
+
end
|
47
|
+
|
48
|
+
module ClassMethods
|
49
|
+
def view_cache_dependency(&dependency)
|
50
|
+
self._view_cache_dependencies += [dependency]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def view_cache_dependencies
|
55
|
+
self.class._view_cache_dependencies.filter_map { |dep| instance_exec(&dep) }
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
# Convenience accessor.
|
60
|
+
def cache(key, options = {}, &block) # :doc:
|
61
|
+
if cache_configured?
|
62
|
+
cache_store.fetch(ActiveSupport::Cache.expand_cache_key(key, :controller), options, &block)
|
63
|
+
else
|
64
|
+
yield
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,265 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
module AbstractController
|
6
|
+
# # Abstract Controller Callbacks
|
7
|
+
#
|
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:
|
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
|
+
module Callbacks
|
25
|
+
extend ActiveSupport::Concern
|
26
|
+
|
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
|
+
include ActiveSupport::Callbacks
|
31
|
+
|
32
|
+
included do
|
33
|
+
define_callbacks :process_action,
|
34
|
+
terminator: ->(controller, result_lambda) { result_lambda.call; controller.performed? },
|
35
|
+
skip_after_callbacks_if_terminated: true
|
36
|
+
mattr_accessor :raise_on_missing_callback_actions, default: false
|
37
|
+
end
|
38
|
+
|
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
|
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?
|
72
|
+
end
|
73
|
+
|
74
|
+
module ClassMethods
|
75
|
+
# If `:only` or `:except` are used, convert the options into the `:if` and
|
76
|
+
# `:unless` options of ActiveSupport::Callbacks.
|
77
|
+
#
|
78
|
+
# The basic idea is that `:only => :index` gets converted to `:if => proc {|c|
|
79
|
+
# c.action_name == "index" }`.
|
80
|
+
#
|
81
|
+
# Note that `:only` has priority over `:if` in case they are used together.
|
82
|
+
#
|
83
|
+
# only: :index, if: -> { true } # the :if option will be ignored.
|
84
|
+
#
|
85
|
+
# Note that `:if` has priority over `:except` in case they are used together.
|
86
|
+
#
|
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.
|
92
|
+
#
|
93
|
+
def _normalize_callback_options(options)
|
94
|
+
_normalize_callback_option(options, :only, :if)
|
95
|
+
_normalize_callback_option(options, :except, :unless)
|
96
|
+
end
|
97
|
+
|
98
|
+
def _normalize_callback_option(options, from, to) # :nodoc:
|
99
|
+
if from_value = options.delete(from)
|
100
|
+
filters = options[:filters]
|
101
|
+
from_value = ActionFilter.new(filters, from, from_value)
|
102
|
+
options[to] = Array(options[to]).unshift(from_value)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
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
|
+
#
|
120
|
+
def _insert_callbacks(callbacks, block = nil)
|
121
|
+
options = callbacks.extract_options!
|
122
|
+
callbacks.push(block) if block
|
123
|
+
options[:filters] = callbacks
|
124
|
+
_normalize_callback_options(options)
|
125
|
+
options.delete(:filters)
|
126
|
+
callbacks.each do |callback|
|
127
|
+
yield callback, options
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
##
|
132
|
+
# :method: before_action
|
133
|
+
#
|
134
|
+
# :call-seq: before_action(names, block)
|
135
|
+
#
|
136
|
+
# Append a callback before actions. See _insert_callbacks for parameter details.
|
137
|
+
#
|
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.
|
141
|
+
|
142
|
+
##
|
143
|
+
# :method: prepend_before_action
|
144
|
+
#
|
145
|
+
# :call-seq: prepend_before_action(names, block)
|
146
|
+
#
|
147
|
+
# Prepend a callback before actions. See _insert_callbacks for parameter
|
148
|
+
# details.
|
149
|
+
#
|
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.
|
153
|
+
|
154
|
+
##
|
155
|
+
# :method: skip_before_action
|
156
|
+
#
|
157
|
+
# :call-seq: skip_before_action(names)
|
158
|
+
#
|
159
|
+
# Skip a callback before actions. See _insert_callbacks for parameter details.
|
160
|
+
|
161
|
+
##
|
162
|
+
# :method: append_before_action
|
163
|
+
#
|
164
|
+
# :call-seq: append_before_action(names, block)
|
165
|
+
#
|
166
|
+
# Append a callback before actions. See _insert_callbacks for parameter details.
|
167
|
+
#
|
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.
|
171
|
+
|
172
|
+
##
|
173
|
+
# :method: after_action
|
174
|
+
#
|
175
|
+
# :call-seq: after_action(names, block)
|
176
|
+
#
|
177
|
+
# Append a callback after actions. See _insert_callbacks for parameter details.
|
178
|
+
|
179
|
+
##
|
180
|
+
# :method: prepend_after_action
|
181
|
+
#
|
182
|
+
# :call-seq: prepend_after_action(names, block)
|
183
|
+
#
|
184
|
+
# Prepend a callback after actions. See _insert_callbacks for parameter details.
|
185
|
+
|
186
|
+
##
|
187
|
+
# :method: skip_after_action
|
188
|
+
#
|
189
|
+
# :call-seq: skip_after_action(names)
|
190
|
+
#
|
191
|
+
# Skip a callback after actions. See _insert_callbacks for parameter details.
|
192
|
+
|
193
|
+
##
|
194
|
+
# :method: append_after_action
|
195
|
+
#
|
196
|
+
# :call-seq: append_after_action(names, block)
|
197
|
+
#
|
198
|
+
# Append a callback after actions. See _insert_callbacks for parameter details.
|
199
|
+
|
200
|
+
##
|
201
|
+
# :method: around_action
|
202
|
+
#
|
203
|
+
# :call-seq: around_action(names, block)
|
204
|
+
#
|
205
|
+
# Append a callback around actions. See _insert_callbacks for parameter details.
|
206
|
+
|
207
|
+
##
|
208
|
+
# :method: prepend_around_action
|
209
|
+
#
|
210
|
+
# :call-seq: prepend_around_action(names, block)
|
211
|
+
#
|
212
|
+
# Prepend a callback around actions. See _insert_callbacks for parameter
|
213
|
+
# details.
|
214
|
+
|
215
|
+
##
|
216
|
+
# :method: skip_around_action
|
217
|
+
#
|
218
|
+
# :call-seq: skip_around_action(names)
|
219
|
+
#
|
220
|
+
# Skip a callback around actions. See _insert_callbacks for parameter details.
|
221
|
+
|
222
|
+
##
|
223
|
+
# :method: append_around_action
|
224
|
+
#
|
225
|
+
# :call-seq: append_around_action(names, block)
|
226
|
+
#
|
227
|
+
# Append a callback around actions. See _insert_callbacks for parameter details.
|
228
|
+
# set up before_action, prepend_before_action, skip_before_action, etc. for each
|
229
|
+
# of before, after, and around.
|
230
|
+
[:before, :after, :around].each do |callback|
|
231
|
+
define_method "#{callback}_action" do |*names, &blk|
|
232
|
+
_insert_callbacks(names, blk) do |name, options|
|
233
|
+
set_callback(:process_action, callback, name, options)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
define_method "prepend_#{callback}_action" do |*names, &blk|
|
238
|
+
_insert_callbacks(names, blk) do |name, options|
|
239
|
+
set_callback(:process_action, callback, name, options.merge(prepend: true))
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
# Skip a before, after or around callback. See _insert_callbacks for details on
|
244
|
+
# the allowed parameters.
|
245
|
+
define_method "skip_#{callback}_action" do |*names|
|
246
|
+
_insert_callbacks(names) do |name, options|
|
247
|
+
skip_callback(:process_action, callback, name, options)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
# *_action is the same as append_*_action
|
252
|
+
alias_method :"append_#{callback}_action", :"#{callback}_action"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
private
|
257
|
+
# Override `AbstractController::Base#process_action` to run the `process_action`
|
258
|
+
# callbacks around the normal behavior.
|
259
|
+
def process_action(...)
|
260
|
+
run_callbacks(:process_action) do
|
261
|
+
super
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "action_dispatch/http/mime_type"
|
6
|
+
|
7
|
+
module AbstractController
|
8
|
+
module Collector
|
9
|
+
def self.generate_method_for_mime(mime)
|
10
|
+
sym = mime.is_a?(Symbol) ? mime : mime.to_sym
|
11
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
12
|
+
def #{sym}(...)
|
13
|
+
custom(Mime[:#{sym}], ...)
|
14
|
+
end
|
15
|
+
RUBY
|
16
|
+
end
|
17
|
+
|
18
|
+
Mime::SET.each do |mime|
|
19
|
+
generate_method_for_mime(mime)
|
20
|
+
end
|
21
|
+
|
22
|
+
Mime::Type.register_callback do |mime|
|
23
|
+
generate_method_for_mime(mime) unless instance_methods.include?(mime.to_sym)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def method_missing(symbol, ...)
|
28
|
+
unless mime_constant = Mime[symbol]
|
29
|
+
raise NoMethodError, "To respond to a custom format, register it as a MIME type first: " \
|
30
|
+
"https://guides.rubyonrails.org/action_controller_overview.html#restful-downloads. " \
|
31
|
+
"If you meant to respond to a variant like :tablet or :phone, not a custom format, " \
|
32
|
+
"be sure to nest your variant response within a format response: " \
|
33
|
+
"format.html { |html| html.tablet { ... } }"
|
34
|
+
end
|
35
|
+
|
36
|
+
if Mime::SET.include?(mime_constant)
|
37
|
+
AbstractController::Collector.generate_method_for_mime(mime_constant)
|
38
|
+
public_send(symbol, ...)
|
39
|
+
else
|
40
|
+
super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,243 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "active_support/dependencies"
|
6
|
+
require "active_support/core_ext/name_error"
|
7
|
+
|
8
|
+
module AbstractController
|
9
|
+
module Helpers
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
included do
|
13
|
+
class_attribute :_helper_methods, default: Array.new
|
14
|
+
|
15
|
+
# This is here so that it is always higher in the inheritance chain than the
|
16
|
+
# definition in lib/action_view/rendering.rb
|
17
|
+
redefine_singleton_method(:_helpers) do
|
18
|
+
if @_helpers ||= nil
|
19
|
+
@_helpers
|
20
|
+
else
|
21
|
+
superclass._helpers
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
self._helpers = define_helpers_module(self)
|
26
|
+
end
|
27
|
+
|
28
|
+
def _helpers
|
29
|
+
self.class._helpers
|
30
|
+
end
|
31
|
+
|
32
|
+
module Resolution # :nodoc:
|
33
|
+
def modules_for_helpers(modules_or_helper_prefixes)
|
34
|
+
modules_or_helper_prefixes.flatten.map! do |module_or_helper_prefix|
|
35
|
+
case module_or_helper_prefix
|
36
|
+
when Module
|
37
|
+
module_or_helper_prefix
|
38
|
+
when String, Symbol
|
39
|
+
helper_prefix = module_or_helper_prefix.to_s
|
40
|
+
helper_prefix = helper_prefix.camelize unless helper_prefix.start_with?(/[A-Z]/)
|
41
|
+
"#{helper_prefix}Helper".constantize
|
42
|
+
else
|
43
|
+
raise ArgumentError, "helper must be a String, Symbol, or Module"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def all_helpers_from_path(path)
|
49
|
+
helpers = Array(path).flat_map do |_path|
|
50
|
+
names = Dir["#{_path}/**/*_helper.rb"].map { |file| file[_path.to_s.size + 1..-"_helper.rb".size - 1] }
|
51
|
+
names.sort!
|
52
|
+
end
|
53
|
+
helpers.uniq!
|
54
|
+
helpers
|
55
|
+
end
|
56
|
+
|
57
|
+
def helper_modules_from_paths(paths)
|
58
|
+
modules_for_helpers(all_helpers_from_path(paths))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
extend Resolution
|
63
|
+
|
64
|
+
module ClassMethods
|
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.
|
68
|
+
def inherited(klass)
|
69
|
+
# Inherited from parent by default
|
70
|
+
klass._helpers = nil
|
71
|
+
|
72
|
+
klass.class_eval { default_helper_module! } unless klass.anonymous?
|
73
|
+
super
|
74
|
+
end
|
75
|
+
|
76
|
+
attr_writer :_helpers
|
77
|
+
|
78
|
+
include Resolution
|
79
|
+
|
80
|
+
##
|
81
|
+
# :method: modules_for_helpers
|
82
|
+
# :call-seq: modules_for_helpers(modules_or_helper_prefixes)
|
83
|
+
#
|
84
|
+
# Given an array of values like the ones accepted by `helper`, this method
|
85
|
+
# returns an array with the corresponding modules, in the same order.
|
86
|
+
#
|
87
|
+
# ActionController::Base.modules_for_helpers(["application", "chart", "rubygems"])
|
88
|
+
# # => [ApplicationHelper, ChartHelper, RubygemsHelper]
|
89
|
+
#
|
90
|
+
#--
|
91
|
+
# Implemented by Resolution#modules_for_helpers.
|
92
|
+
|
93
|
+
# :method: # all_helpers_from_path
|
94
|
+
# :call-seq: all_helpers_from_path(path)
|
95
|
+
#
|
96
|
+
# Returns a list of helper names in a given path.
|
97
|
+
#
|
98
|
+
# ActionController::Base.all_helpers_from_path 'app/helpers'
|
99
|
+
# # => ["application", "chart", "rubygems"]
|
100
|
+
#
|
101
|
+
#--
|
102
|
+
# Implemented by Resolution#all_helpers_from_path.
|
103
|
+
|
104
|
+
# Declare a controller method as a helper. For example, the following
|
105
|
+
# makes the `current_user` and `logged_in?` controller methods available
|
106
|
+
# to the view:
|
107
|
+
# class ApplicationController < ActionController::Base
|
108
|
+
# helper_method :current_user, :logged_in?
|
109
|
+
#
|
110
|
+
# private
|
111
|
+
# def current_user
|
112
|
+
# @current_user ||= User.find_by(id: session[:user])
|
113
|
+
# end
|
114
|
+
#
|
115
|
+
# def logged_in?
|
116
|
+
# current_user != nil
|
117
|
+
# end
|
118
|
+
# end
|
119
|
+
#
|
120
|
+
# In a view:
|
121
|
+
# <% if logged_in? -%>Welcome, <%= current_user.name %><% end -%>
|
122
|
+
#
|
123
|
+
# #### Parameters
|
124
|
+
# * `method[, method]` - A name or names of a method on the controller to be
|
125
|
+
# made available on the view.
|
126
|
+
def helper_method(*methods)
|
127
|
+
methods.flatten!
|
128
|
+
self._helper_methods += methods
|
129
|
+
|
130
|
+
location = caller_locations(1, 1).first
|
131
|
+
file, line = location.path, location.lineno
|
132
|
+
|
133
|
+
methods.each do |method|
|
134
|
+
# def current_user(...)
|
135
|
+
# controller.send(:'current_user', ...)
|
136
|
+
# end
|
137
|
+
_helpers_for_modification.class_eval <<~ruby_eval.lines.map(&:strip).join(";"), file, line
|
138
|
+
def #{method}(...)
|
139
|
+
controller.send(:'#{method}', ...)
|
140
|
+
end
|
141
|
+
ruby_eval
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Includes the given modules in the template class.
|
146
|
+
#
|
147
|
+
# Modules can be specified in different ways. All of the following calls include
|
148
|
+
# `FooHelper`:
|
149
|
+
#
|
150
|
+
# # Module, recommended.
|
151
|
+
# helper FooHelper
|
152
|
+
#
|
153
|
+
# # String/symbol without the "helper" suffix, camel or snake case.
|
154
|
+
# helper "Foo"
|
155
|
+
# helper :Foo
|
156
|
+
# helper "foo"
|
157
|
+
# helper :foo
|
158
|
+
#
|
159
|
+
# The last two assume that `"foo".camelize` returns "Foo".
|
160
|
+
#
|
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.
|
164
|
+
#
|
165
|
+
# Namespaces are supported. The following calls include `Foo::BarHelper`:
|
166
|
+
#
|
167
|
+
# # Module, recommended.
|
168
|
+
# helper Foo::BarHelper
|
169
|
+
#
|
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"
|
175
|
+
#
|
176
|
+
# The last two assume that `"foo/bar".camelize` returns "Foo::Bar".
|
177
|
+
#
|
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:
|
181
|
+
#
|
182
|
+
# helper do
|
183
|
+
# def wadus
|
184
|
+
# "wadus"
|
185
|
+
# end
|
186
|
+
# end
|
187
|
+
#
|
188
|
+
# Furthermore, all the above styles can be mixed together:
|
189
|
+
#
|
190
|
+
# helper FooHelper, "woo", "bar/baz" do
|
191
|
+
# def wadus
|
192
|
+
# "wadus"
|
193
|
+
# end
|
194
|
+
# end
|
195
|
+
#
|
196
|
+
def helper(*args, &block)
|
197
|
+
modules_for_helpers(args).each do |mod|
|
198
|
+
next if _helpers.include?(mod)
|
199
|
+
_helpers_for_modification.include(mod)
|
200
|
+
end
|
201
|
+
|
202
|
+
_helpers_for_modification.module_eval(&block) if block_given?
|
203
|
+
end
|
204
|
+
|
205
|
+
# Clears up all existing helpers in this class, only keeping the helper with the
|
206
|
+
# same name as this class.
|
207
|
+
def clear_helpers
|
208
|
+
inherited_helper_methods = _helper_methods
|
209
|
+
self._helpers = Module.new
|
210
|
+
self._helper_methods = Array.new
|
211
|
+
|
212
|
+
inherited_helper_methods.each { |meth| helper_method meth }
|
213
|
+
default_helper_module! unless anonymous?
|
214
|
+
end
|
215
|
+
|
216
|
+
def _helpers_for_modification
|
217
|
+
unless @_helpers
|
218
|
+
self._helpers = define_helpers_module(self, superclass._helpers)
|
219
|
+
end
|
220
|
+
_helpers
|
221
|
+
end
|
222
|
+
|
223
|
+
private
|
224
|
+
def define_helpers_module(klass, helpers = nil)
|
225
|
+
# In some tests inherited is called explicitly. In that case, just return the
|
226
|
+
# module from the first time it was defined
|
227
|
+
return klass.const_get(:HelperMethods) if klass.const_defined?(:HelperMethods, false)
|
228
|
+
|
229
|
+
mod = Module.new
|
230
|
+
klass.const_set(:HelperMethods, mod)
|
231
|
+
mod.include(helpers) if helpers
|
232
|
+
mod
|
233
|
+
end
|
234
|
+
|
235
|
+
def default_helper_module!
|
236
|
+
helper_prefix = name.delete_suffix("Controller")
|
237
|
+
helper(helper_prefix)
|
238
|
+
rescue NameError => e
|
239
|
+
raise unless e.missing_name?("#{helper_prefix}Helper")
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "active_support/benchmarkable"
|
6
|
+
|
7
|
+
module AbstractController
|
8
|
+
module Logger # :nodoc:
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
included do
|
12
|
+
config_accessor :logger
|
13
|
+
include ActiveSupport::Benchmarkable
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "active_support/core_ext/module/introspection"
|
6
|
+
|
7
|
+
module AbstractController
|
8
|
+
module Railties
|
9
|
+
module RoutesHelpers
|
10
|
+
def self.with(routes, include_path_helpers = true)
|
11
|
+
Module.new do
|
12
|
+
define_method(:inherited) do |klass|
|
13
|
+
super(klass)
|
14
|
+
|
15
|
+
if namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
|
16
|
+
klass.include(namespace.railtie_routes_url_helpers(include_path_helpers))
|
17
|
+
else
|
18
|
+
klass.include(routes.url_helpers(include_path_helpers))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|