omg-actionpack 8.0.0.alpha1
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.
- 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
|