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.
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