omg-actionpack 8.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (187) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +129 -0
  3. data/MIT-LICENSE +21 -0
  4. data/README.rdoc +57 -0
  5. data/lib/abstract_controller/asset_paths.rb +14 -0
  6. data/lib/abstract_controller/base.rb +299 -0
  7. data/lib/abstract_controller/caching/fragments.rb +149 -0
  8. data/lib/abstract_controller/caching.rb +68 -0
  9. data/lib/abstract_controller/callbacks.rb +265 -0
  10. data/lib/abstract_controller/collector.rb +44 -0
  11. data/lib/abstract_controller/deprecator.rb +9 -0
  12. data/lib/abstract_controller/error.rb +8 -0
  13. data/lib/abstract_controller/helpers.rb +243 -0
  14. data/lib/abstract_controller/logger.rb +16 -0
  15. data/lib/abstract_controller/railties/routes_helpers.rb +25 -0
  16. data/lib/abstract_controller/rendering.rb +126 -0
  17. data/lib/abstract_controller/translation.rb +42 -0
  18. data/lib/abstract_controller/url_for.rb +37 -0
  19. data/lib/abstract_controller.rb +36 -0
  20. data/lib/action_controller/api/api_rendering.rb +18 -0
  21. data/lib/action_controller/api.rb +155 -0
  22. data/lib/action_controller/base.rb +332 -0
  23. data/lib/action_controller/caching.rb +49 -0
  24. data/lib/action_controller/deprecator.rb +9 -0
  25. data/lib/action_controller/form_builder.rb +55 -0
  26. data/lib/action_controller/log_subscriber.rb +96 -0
  27. data/lib/action_controller/metal/allow_browser.rb +123 -0
  28. data/lib/action_controller/metal/basic_implicit_render.rb +17 -0
  29. data/lib/action_controller/metal/conditional_get.rb +341 -0
  30. data/lib/action_controller/metal/content_security_policy.rb +86 -0
  31. data/lib/action_controller/metal/cookies.rb +20 -0
  32. data/lib/action_controller/metal/data_streaming.rb +154 -0
  33. data/lib/action_controller/metal/default_headers.rb +21 -0
  34. data/lib/action_controller/metal/etag_with_flash.rb +22 -0
  35. data/lib/action_controller/metal/etag_with_template_digest.rb +59 -0
  36. data/lib/action_controller/metal/exceptions.rb +106 -0
  37. data/lib/action_controller/metal/flash.rb +67 -0
  38. data/lib/action_controller/metal/head.rb +67 -0
  39. data/lib/action_controller/metal/helpers.rb +129 -0
  40. data/lib/action_controller/metal/http_authentication.rb +565 -0
  41. data/lib/action_controller/metal/implicit_render.rb +67 -0
  42. data/lib/action_controller/metal/instrumentation.rb +120 -0
  43. data/lib/action_controller/metal/live.rb +398 -0
  44. data/lib/action_controller/metal/logging.rb +22 -0
  45. data/lib/action_controller/metal/mime_responds.rb +337 -0
  46. data/lib/action_controller/metal/parameter_encoding.rb +84 -0
  47. data/lib/action_controller/metal/params_wrapper.rb +312 -0
  48. data/lib/action_controller/metal/permissions_policy.rb +38 -0
  49. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  50. data/lib/action_controller/metal/redirecting.rb +251 -0
  51. data/lib/action_controller/metal/renderers.rb +181 -0
  52. data/lib/action_controller/metal/rendering.rb +260 -0
  53. data/lib/action_controller/metal/request_forgery_protection.rb +667 -0
  54. data/lib/action_controller/metal/rescue.rb +33 -0
  55. data/lib/action_controller/metal/streaming.rb +183 -0
  56. data/lib/action_controller/metal/strong_parameters.rb +1546 -0
  57. data/lib/action_controller/metal/testing.rb +25 -0
  58. data/lib/action_controller/metal/url_for.rb +65 -0
  59. data/lib/action_controller/metal.rb +339 -0
  60. data/lib/action_controller/railtie.rb +149 -0
  61. data/lib/action_controller/railties/helpers.rb +26 -0
  62. data/lib/action_controller/renderer.rb +161 -0
  63. data/lib/action_controller/template_assertions.rb +13 -0
  64. data/lib/action_controller/test_case.rb +691 -0
  65. data/lib/action_controller.rb +80 -0
  66. data/lib/action_dispatch/constants.rb +34 -0
  67. data/lib/action_dispatch/deprecator.rb +9 -0
  68. data/lib/action_dispatch/http/cache.rb +249 -0
  69. data/lib/action_dispatch/http/content_disposition.rb +47 -0
  70. data/lib/action_dispatch/http/content_security_policy.rb +365 -0
  71. data/lib/action_dispatch/http/filter_parameters.rb +80 -0
  72. data/lib/action_dispatch/http/filter_redirect.rb +50 -0
  73. data/lib/action_dispatch/http/headers.rb +134 -0
  74. data/lib/action_dispatch/http/mime_negotiation.rb +187 -0
  75. data/lib/action_dispatch/http/mime_type.rb +389 -0
  76. data/lib/action_dispatch/http/mime_types.rb +54 -0
  77. data/lib/action_dispatch/http/parameters.rb +119 -0
  78. data/lib/action_dispatch/http/permissions_policy.rb +189 -0
  79. data/lib/action_dispatch/http/rack_cache.rb +67 -0
  80. data/lib/action_dispatch/http/request.rb +498 -0
  81. data/lib/action_dispatch/http/response.rb +556 -0
  82. data/lib/action_dispatch/http/upload.rb +107 -0
  83. data/lib/action_dispatch/http/url.rb +344 -0
  84. data/lib/action_dispatch/journey/formatter.rb +226 -0
  85. data/lib/action_dispatch/journey/gtg/builder.rb +149 -0
  86. data/lib/action_dispatch/journey/gtg/simulator.rb +50 -0
  87. data/lib/action_dispatch/journey/gtg/transition_table.rb +217 -0
  88. data/lib/action_dispatch/journey/nfa/dot.rb +27 -0
  89. data/lib/action_dispatch/journey/nodes/node.rb +208 -0
  90. data/lib/action_dispatch/journey/parser.rb +103 -0
  91. data/lib/action_dispatch/journey/path/pattern.rb +209 -0
  92. data/lib/action_dispatch/journey/route.rb +189 -0
  93. data/lib/action_dispatch/journey/router/utils.rb +105 -0
  94. data/lib/action_dispatch/journey/router.rb +151 -0
  95. data/lib/action_dispatch/journey/routes.rb +82 -0
  96. data/lib/action_dispatch/journey/scanner.rb +70 -0
  97. data/lib/action_dispatch/journey/visitors.rb +267 -0
  98. data/lib/action_dispatch/journey/visualizer/fsm.css +30 -0
  99. data/lib/action_dispatch/journey/visualizer/fsm.js +159 -0
  100. data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
  101. data/lib/action_dispatch/journey.rb +7 -0
  102. data/lib/action_dispatch/log_subscriber.rb +25 -0
  103. data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
  104. data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
  105. data/lib/action_dispatch/middleware/callbacks.rb +38 -0
  106. data/lib/action_dispatch/middleware/cookies.rb +719 -0
  107. data/lib/action_dispatch/middleware/debug_exceptions.rb +206 -0
  108. data/lib/action_dispatch/middleware/debug_locks.rb +129 -0
  109. data/lib/action_dispatch/middleware/debug_view.rb +73 -0
  110. data/lib/action_dispatch/middleware/exception_wrapper.rb +350 -0
  111. data/lib/action_dispatch/middleware/executor.rb +32 -0
  112. data/lib/action_dispatch/middleware/flash.rb +318 -0
  113. data/lib/action_dispatch/middleware/host_authorization.rb +171 -0
  114. data/lib/action_dispatch/middleware/public_exceptions.rb +64 -0
  115. data/lib/action_dispatch/middleware/reloader.rb +16 -0
  116. data/lib/action_dispatch/middleware/remote_ip.rb +199 -0
  117. data/lib/action_dispatch/middleware/request_id.rb +50 -0
  118. data/lib/action_dispatch/middleware/server_timing.rb +78 -0
  119. data/lib/action_dispatch/middleware/session/abstract_store.rb +112 -0
  120. data/lib/action_dispatch/middleware/session/cache_store.rb +66 -0
  121. data/lib/action_dispatch/middleware/session/cookie_store.rb +129 -0
  122. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +34 -0
  123. data/lib/action_dispatch/middleware/show_exceptions.rb +88 -0
  124. data/lib/action_dispatch/middleware/ssl.rb +180 -0
  125. data/lib/action_dispatch/middleware/stack.rb +194 -0
  126. data/lib/action_dispatch/middleware/static.rb +192 -0
  127. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  128. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  129. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
  130. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +17 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
  132. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +36 -0
  133. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +62 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
  136. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +12 -0
  137. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +9 -0
  138. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +35 -0
  139. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
  140. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
  141. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +16 -0
  142. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +284 -0
  143. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +23 -0
  144. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  145. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
  146. data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
  147. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +32 -0
  148. data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
  149. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
  150. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
  151. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +6 -0
  152. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
  153. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +19 -0
  154. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +232 -0
  155. data/lib/action_dispatch/railtie.rb +77 -0
  156. data/lib/action_dispatch/request/session.rb +283 -0
  157. data/lib/action_dispatch/request/utils.rb +109 -0
  158. data/lib/action_dispatch/routing/endpoint.rb +19 -0
  159. data/lib/action_dispatch/routing/inspector.rb +323 -0
  160. data/lib/action_dispatch/routing/mapper.rb +2372 -0
  161. data/lib/action_dispatch/routing/polymorphic_routes.rb +363 -0
  162. data/lib/action_dispatch/routing/redirection.rb +218 -0
  163. data/lib/action_dispatch/routing/route_set.rb +958 -0
  164. data/lib/action_dispatch/routing/routes_proxy.rb +66 -0
  165. data/lib/action_dispatch/routing/url_for.rb +244 -0
  166. data/lib/action_dispatch/routing.rb +262 -0
  167. data/lib/action_dispatch/system_test_case.rb +206 -0
  168. data/lib/action_dispatch/system_testing/browser.rb +75 -0
  169. data/lib/action_dispatch/system_testing/driver.rb +85 -0
  170. data/lib/action_dispatch/system_testing/server.rb +33 -0
  171. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +164 -0
  172. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +23 -0
  173. data/lib/action_dispatch/testing/assertion_response.rb +48 -0
  174. data/lib/action_dispatch/testing/assertions/response.rb +114 -0
  175. data/lib/action_dispatch/testing/assertions/routing.rb +343 -0
  176. data/lib/action_dispatch/testing/assertions.rb +25 -0
  177. data/lib/action_dispatch/testing/integration.rb +694 -0
  178. data/lib/action_dispatch/testing/request_encoder.rb +60 -0
  179. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  180. data/lib/action_dispatch/testing/test_process.rb +57 -0
  181. data/lib/action_dispatch/testing/test_request.rb +73 -0
  182. data/lib/action_dispatch/testing/test_response.rb +58 -0
  183. data/lib/action_dispatch.rb +147 -0
  184. data/lib/action_pack/gem_version.rb +19 -0
  185. data/lib/action_pack/version.rb +12 -0
  186. data/lib/action_pack.rb +27 -0
  187. 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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ module AbstractController
6
+ def self.deprecator # :nodoc:
7
+ @deprecator ||= ActiveSupport::Deprecation.new
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ module AbstractController
6
+ class Error < StandardError # :nodoc:
7
+ end
8
+ 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