activesupport 7.0.8.7 → 7.2.2.1

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 (198) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +143 -459
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/lib/active_support/actionable_error.rb +3 -1
  6. data/lib/active_support/array_inquirer.rb +3 -1
  7. data/lib/active_support/backtrace_cleaner.rb +39 -7
  8. data/lib/active_support/benchmarkable.rb +1 -0
  9. data/lib/active_support/broadcast_logger.rb +251 -0
  10. data/lib/active_support/builder.rb +1 -1
  11. data/lib/active_support/cache/coder.rb +153 -0
  12. data/lib/active_support/cache/entry.rb +134 -0
  13. data/lib/active_support/cache/file_store.rb +49 -17
  14. data/lib/active_support/cache/mem_cache_store.rb +94 -128
  15. data/lib/active_support/cache/memory_store.rb +80 -25
  16. data/lib/active_support/cache/null_store.rb +6 -0
  17. data/lib/active_support/cache/redis_cache_store.rb +165 -152
  18. data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
  19. data/lib/active_support/cache/strategy/local_cache.rb +29 -14
  20. data/lib/active_support/cache.rb +363 -291
  21. data/lib/active_support/callbacks.rb +118 -134
  22. data/lib/active_support/code_generator.rb +15 -10
  23. data/lib/active_support/concern.rb +4 -2
  24. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
  25. data/lib/active_support/concurrency/null_lock.rb +13 -0
  26. data/lib/active_support/configurable.rb +10 -0
  27. data/lib/active_support/core_ext/array/conversions.rb +1 -2
  28. data/lib/active_support/core_ext/array.rb +0 -1
  29. data/lib/active_support/core_ext/class/subclasses.rb +17 -34
  30. data/lib/active_support/core_ext/date/blank.rb +4 -0
  31. data/lib/active_support/core_ext/date/conversions.rb +1 -2
  32. data/lib/active_support/core_ext/date.rb +0 -1
  33. data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
  34. data/lib/active_support/core_ext/date_and_time/compatibility.rb +28 -1
  35. data/lib/active_support/core_ext/date_time/blank.rb +4 -0
  36. data/lib/active_support/core_ext/date_time/conversions.rb +2 -2
  37. data/lib/active_support/core_ext/date_time.rb +0 -1
  38. data/lib/active_support/core_ext/digest/uuid.rb +7 -10
  39. data/lib/active_support/core_ext/enumerable.rb +3 -75
  40. data/lib/active_support/core_ext/erb/util.rb +201 -0
  41. data/lib/active_support/core_ext/hash/conversions.rb +1 -1
  42. data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
  43. data/lib/active_support/core_ext/hash/keys.rb +4 -4
  44. data/lib/active_support/core_ext/module/attr_internal.rb +17 -6
  45. data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
  46. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
  47. data/lib/active_support/core_ext/module/concerning.rb +6 -6
  48. data/lib/active_support/core_ext/module/delegation.rb +20 -119
  49. data/lib/active_support/core_ext/module/deprecation.rb +12 -12
  50. data/lib/active_support/core_ext/module/introspection.rb +0 -1
  51. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  52. data/lib/active_support/core_ext/numeric/conversions.rb +5 -3
  53. data/lib/active_support/core_ext/numeric.rb +0 -1
  54. data/lib/active_support/core_ext/object/blank.rb +45 -1
  55. data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
  56. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  57. data/lib/active_support/core_ext/object/instance_variables.rb +4 -2
  58. data/lib/active_support/core_ext/object/json.rb +17 -7
  59. data/lib/active_support/core_ext/object/with.rb +46 -0
  60. data/lib/active_support/core_ext/object/with_options.rb +4 -4
  61. data/lib/active_support/core_ext/object.rb +1 -0
  62. data/lib/active_support/core_ext/pathname/blank.rb +20 -0
  63. data/lib/active_support/core_ext/pathname/existence.rb +2 -0
  64. data/lib/active_support/core_ext/pathname.rb +1 -0
  65. data/lib/active_support/core_ext/range/conversions.rb +28 -7
  66. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  67. data/lib/active_support/core_ext/range.rb +1 -2
  68. data/lib/active_support/core_ext/securerandom.rb +1 -5
  69. data/lib/active_support/core_ext/string/conversions.rb +1 -1
  70. data/lib/active_support/core_ext/string/filters.rb +21 -15
  71. data/lib/active_support/core_ext/string/indent.rb +1 -1
  72. data/lib/active_support/core_ext/string/inflections.rb +16 -5
  73. data/lib/active_support/core_ext/string/multibyte.rb +1 -1
  74. data/lib/active_support/core_ext/string/output_safety.rb +34 -177
  75. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  76. data/lib/active_support/core_ext/time/calculations.rb +36 -30
  77. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  78. data/lib/active_support/core_ext/time/conversions.rb +1 -3
  79. data/lib/active_support/core_ext/time/zones.rb +4 -4
  80. data/lib/active_support/core_ext/time.rb +0 -1
  81. data/lib/active_support/core_ext.rb +0 -1
  82. data/lib/active_support/current_attributes.rb +53 -46
  83. data/lib/active_support/deep_mergeable.rb +53 -0
  84. data/lib/active_support/delegation.rb +202 -0
  85. data/lib/active_support/dependencies/autoload.rb +9 -16
  86. data/lib/active_support/deprecation/behaviors.rb +65 -42
  87. data/lib/active_support/deprecation/constant_accessor.rb +47 -25
  88. data/lib/active_support/deprecation/deprecators.rb +104 -0
  89. data/lib/active_support/deprecation/disallowed.rb +3 -5
  90. data/lib/active_support/deprecation/method_wrappers.rb +6 -23
  91. data/lib/active_support/deprecation/proxy_wrappers.rb +34 -22
  92. data/lib/active_support/deprecation/reporting.rb +49 -27
  93. data/lib/active_support/deprecation.rb +39 -9
  94. data/lib/active_support/deprecator.rb +7 -0
  95. data/lib/active_support/descendants_tracker.rb +66 -172
  96. data/lib/active_support/duration/iso8601_parser.rb +2 -2
  97. data/lib/active_support/duration/iso8601_serializer.rb +1 -4
  98. data/lib/active_support/duration.rb +13 -7
  99. data/lib/active_support/encrypted_configuration.rb +30 -9
  100. data/lib/active_support/encrypted_file.rb +9 -4
  101. data/lib/active_support/environment_inquirer.rb +22 -2
  102. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  103. data/lib/active_support/error_reporter.rb +160 -36
  104. data/lib/active_support/evented_file_update_checker.rb +0 -1
  105. data/lib/active_support/execution_wrapper.rb +4 -5
  106. data/lib/active_support/file_update_checker.rb +5 -3
  107. data/lib/active_support/fork_tracker.rb +4 -32
  108. data/lib/active_support/gem_version.rb +4 -4
  109. data/lib/active_support/gzip.rb +2 -0
  110. data/lib/active_support/hash_with_indifferent_access.rb +41 -25
  111. data/lib/active_support/html_safe_translation.rb +19 -6
  112. data/lib/active_support/i18n.rb +1 -1
  113. data/lib/active_support/i18n_railtie.rb +20 -13
  114. data/lib/active_support/inflector/inflections.rb +2 -0
  115. data/lib/active_support/inflector/methods.rb +23 -11
  116. data/lib/active_support/inflector/transliterate.rb +3 -1
  117. data/lib/active_support/isolated_execution_state.rb +26 -22
  118. data/lib/active_support/json/decoding.rb +2 -1
  119. data/lib/active_support/json/encoding.rb +25 -43
  120. data/lib/active_support/key_generator.rb +9 -1
  121. data/lib/active_support/lazy_load_hooks.rb +6 -4
  122. data/lib/active_support/locale/en.yml +2 -0
  123. data/lib/active_support/log_subscriber.rb +74 -34
  124. data/lib/active_support/logger.rb +22 -60
  125. data/lib/active_support/logger_thread_safe_level.rb +10 -32
  126. data/lib/active_support/message_encryptor.rb +197 -53
  127. data/lib/active_support/message_encryptors.rb +141 -0
  128. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  129. data/lib/active_support/message_pack/extensions.rb +305 -0
  130. data/lib/active_support/message_pack/serializer.rb +63 -0
  131. data/lib/active_support/message_pack.rb +50 -0
  132. data/lib/active_support/message_verifier.rb +220 -89
  133. data/lib/active_support/message_verifiers.rb +135 -0
  134. data/lib/active_support/messages/codec.rb +65 -0
  135. data/lib/active_support/messages/metadata.rb +111 -45
  136. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  137. data/lib/active_support/messages/rotator.rb +34 -32
  138. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  139. data/lib/active_support/multibyte/chars.rb +4 -2
  140. data/lib/active_support/multibyte/unicode.rb +9 -37
  141. data/lib/active_support/notifications/fanout.rb +248 -87
  142. data/lib/active_support/notifications/instrumenter.rb +93 -25
  143. data/lib/active_support/notifications.rb +29 -28
  144. data/lib/active_support/number_helper/number_converter.rb +16 -7
  145. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -6
  146. data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -3
  147. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
  148. data/lib/active_support/number_helper.rb +379 -318
  149. data/lib/active_support/option_merger.rb +2 -2
  150. data/lib/active_support/ordered_hash.rb +3 -3
  151. data/lib/active_support/ordered_options.rb +67 -15
  152. data/lib/active_support/parameter_filter.rb +84 -69
  153. data/lib/active_support/proxy_object.rb +8 -3
  154. data/lib/active_support/railtie.rb +25 -20
  155. data/lib/active_support/reloader.rb +12 -4
  156. data/lib/active_support/rescuable.rb +2 -0
  157. data/lib/active_support/secure_compare_rotator.rb +16 -9
  158. data/lib/active_support/string_inquirer.rb +4 -2
  159. data/lib/active_support/subscriber.rb +10 -27
  160. data/lib/active_support/syntax_error_proxy.rb +60 -0
  161. data/lib/active_support/tagged_logging.rb +64 -25
  162. data/lib/active_support/test_case.rb +156 -7
  163. data/lib/active_support/testing/assertions.rb +28 -12
  164. data/lib/active_support/testing/autorun.rb +0 -2
  165. data/lib/active_support/testing/constant_stubbing.rb +54 -0
  166. data/lib/active_support/testing/deprecation.rb +20 -27
  167. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  168. data/lib/active_support/testing/isolation.rb +21 -9
  169. data/lib/active_support/testing/method_call_assertions.rb +7 -8
  170. data/lib/active_support/testing/parallelization/server.rb +3 -0
  171. data/lib/active_support/testing/parallelize_executor.rb +8 -3
  172. data/lib/active_support/testing/setup_and_teardown.rb +2 -0
  173. data/lib/active_support/testing/stream.rb +1 -1
  174. data/lib/active_support/testing/strict_warnings.rb +43 -0
  175. data/lib/active_support/testing/tests_without_assertions.rb +19 -0
  176. data/lib/active_support/testing/time_helpers.rb +38 -16
  177. data/lib/active_support/time_with_zone.rb +12 -18
  178. data/lib/active_support/values/time_zone.rb +25 -14
  179. data/lib/active_support/version.rb +1 -1
  180. data/lib/active_support/xml_mini/jdom.rb +3 -10
  181. data/lib/active_support/xml_mini/nokogiri.rb +1 -1
  182. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  183. data/lib/active_support/xml_mini/rexml.rb +1 -1
  184. data/lib/active_support/xml_mini.rb +12 -3
  185. data/lib/active_support.rb +15 -3
  186. metadata +140 -19
  187. data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
  188. data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -40
  189. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -36
  190. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
  191. data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -36
  192. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -5
  193. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  194. data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -73
  195. data/lib/active_support/core_ext/uri.rb +0 -5
  196. data/lib/active_support/deprecation/instance_delegator.rb +0 -38
  197. data/lib/active_support/per_thread_registry.rb +0 -65
  198. data/lib/active_support/ruby_features.rb +0 -7
@@ -9,7 +9,9 @@ require "active_support/core_ext/object/blank"
9
9
  require "thread"
10
10
 
11
11
  module ActiveSupport
12
- # Callbacks are code hooks that are run at key points in an object's life cycle.
12
+ # = Active Support \Callbacks
13
+ #
14
+ # \Callbacks are code hooks that are run at key points in an object's life cycle.
13
15
  # The typical use case is to have a base class define a set of callbacks
14
16
  # relevant to the other functionality it supplies, so that subclasses can
15
17
  # install callbacks that enhance or modify the base functionality without
@@ -68,7 +70,7 @@ module ActiveSupport
68
70
  class_attribute :__callbacks, instance_writer: false, default: {}
69
71
  end
70
72
 
71
- CALLBACK_FILTER_TYPES = [:before, :after, :around]
73
+ CALLBACK_FILTER_TYPES = [:before, :after, :around].freeze
72
74
 
73
75
  # Runs the callbacks for the given event.
74
76
  #
@@ -92,14 +94,15 @@ module ActiveSupport
92
94
  # callback can be as noisy as it likes -- but when control has passed
93
95
  # smoothly through and into the supplied block, we want as little evidence
94
96
  # as possible that we were here.
95
- def run_callbacks(kind)
97
+ def run_callbacks(kind, type = nil)
96
98
  callbacks = __callbacks[kind.to_sym]
97
99
 
98
100
  if callbacks.empty?
99
101
  yield if block_given?
100
102
  else
101
103
  env = Filters::Environment.new(self, false, nil)
102
- next_sequence = callbacks.compile
104
+
105
+ next_sequence = callbacks.compile(type)
103
106
 
104
107
  # Common case: no 'around' callbacks defined
105
108
  if next_sequence.final?
@@ -147,7 +150,7 @@ module ActiveSupport
147
150
  def halted_callback_hook(filter, name)
148
151
  end
149
152
 
150
- module Conditionals # :nodoc:
153
+ module Conditionals # :nodoc: all
151
154
  class Value
152
155
  def initialize(&block)
153
156
  @block = block
@@ -156,128 +159,76 @@ module ActiveSupport
156
159
  end
157
160
  end
158
161
 
159
- module Filters
162
+ module Filters # :nodoc: all
160
163
  Environment = Struct.new(:target, :halted, :value)
161
164
 
162
165
  class Before
163
- def self.build(callback_sequence, user_callback, user_conditions, chain_config, filter, name)
166
+ def initialize(user_callback, user_conditions, chain_config, filter, name)
164
167
  halted_lambda = chain_config[:terminator]
165
-
166
- if user_conditions.any?
167
- halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter, name)
168
- else
169
- halting(callback_sequence, user_callback, halted_lambda, filter, name)
170
- end
168
+ @user_callback, @user_conditions, @halted_lambda, @filter, @name = user_callback, user_conditions, halted_lambda, filter, name
169
+ freeze
171
170
  end
171
+ attr_reader :user_callback, :user_conditions, :halted_lambda, :filter, :name
172
172
 
173
- def self.halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter, name)
174
- callback_sequence.before do |env|
175
- target = env.target
176
- value = env.value
177
- halted = env.halted
173
+ def call(env)
174
+ target = env.target
175
+ value = env.value
176
+ halted = env.halted
178
177
 
179
- if !halted && user_conditions.all? { |c| c.call(target, value) }
180
- result_lambda = -> { user_callback.call target, value }
181
- env.halted = halted_lambda.call(target, result_lambda)
182
- if env.halted
183
- target.send :halted_callback_hook, filter, name
184
- end
178
+ if !halted && user_conditions.all? { |c| c.call(target, value) }
179
+ result_lambda = -> { user_callback.call target, value }
180
+ env.halted = halted_lambda.call(target, result_lambda)
181
+ if env.halted
182
+ target.send :halted_callback_hook, filter, name
185
183
  end
186
-
187
- env
188
184
  end
189
- end
190
- private_class_method :halting_and_conditional
191
-
192
- def self.halting(callback_sequence, user_callback, halted_lambda, filter, name)
193
- callback_sequence.before do |env|
194
- target = env.target
195
- value = env.value
196
- halted = env.halted
197
185
 
198
- unless halted
199
- result_lambda = -> { user_callback.call target, value }
200
- env.halted = halted_lambda.call(target, result_lambda)
201
- if env.halted
202
- target.send :halted_callback_hook, filter, name
203
- end
204
- end
186
+ env
187
+ end
205
188
 
206
- env
207
- end
189
+ def apply(callback_sequence)
190
+ callback_sequence.before(self)
208
191
  end
209
- private_class_method :halting
210
192
  end
211
193
 
212
194
  class After
213
- def self.build(callback_sequence, user_callback, user_conditions, chain_config)
214
- if chain_config[:skip_after_callbacks_if_terminated]
215
- if user_conditions.any?
216
- halting_and_conditional(callback_sequence, user_callback, user_conditions)
217
- else
218
- halting(callback_sequence, user_callback)
219
- end
220
- else
221
- if user_conditions.any?
222
- conditional callback_sequence, user_callback, user_conditions
223
- else
224
- simple callback_sequence, user_callback
225
- end
226
- end
195
+ attr_reader :user_callback, :user_conditions, :halting
196
+ def initialize(user_callback, user_conditions, chain_config)
197
+ halting = chain_config[:skip_after_callbacks_if_terminated]
198
+ @user_callback, @user_conditions, @halting = user_callback, user_conditions, halting
199
+ freeze
227
200
  end
228
201
 
229
- def self.halting_and_conditional(callback_sequence, user_callback, user_conditions)
230
- callback_sequence.after do |env|
231
- target = env.target
232
- value = env.value
233
- halted = env.halted
234
-
235
- if !halted && user_conditions.all? { |c| c.call(target, value) }
236
- user_callback.call target, value
237
- end
202
+ def call(env)
203
+ target = env.target
204
+ value = env.value
205
+ halted = env.halted
238
206
 
239
- env
207
+ if (!halted || !@halting) && user_conditions.all? { |c| c.call(target, value) }
208
+ user_callback.call target, value
240
209
  end
241
- end
242
- private_class_method :halting_and_conditional
243
210
 
244
- def self.halting(callback_sequence, user_callback)
245
- callback_sequence.after do |env|
246
- unless env.halted
247
- user_callback.call env.target, env.value
248
- end
249
-
250
- env
251
- end
211
+ env
252
212
  end
253
- private_class_method :halting
254
-
255
- def self.conditional(callback_sequence, user_callback, user_conditions)
256
- callback_sequence.after do |env|
257
- target = env.target
258
- value = env.value
259
213
 
260
- if user_conditions.all? { |c| c.call(target, value) }
261
- user_callback.call target, value
262
- end
263
-
264
- env
265
- end
214
+ def apply(callback_sequence)
215
+ callback_sequence.after(self)
266
216
  end
267
- private_class_method :conditional
217
+ end
268
218
 
269
- def self.simple(callback_sequence, user_callback)
270
- callback_sequence.after do |env|
271
- user_callback.call env.target, env.value
219
+ class Around
220
+ def initialize(user_callback, user_conditions)
221
+ @user_callback, @user_conditions = user_callback, user_conditions
222
+ freeze
223
+ end
272
224
 
273
- env
274
- end
225
+ def apply(callback_sequence)
226
+ callback_sequence.around(@user_callback, @user_conditions)
275
227
  end
276
- private_class_method :simple
277
228
  end
278
229
  end
279
230
 
280
- class Callback # :nodoc:#
231
+ class Callback # :nodoc:
281
232
  def self.build(chain, filter, kind, options)
282
233
  if filter.is_a?(String)
283
234
  raise ArgumentError, <<-MSG.squish
@@ -299,6 +250,8 @@ module ActiveSupport
299
250
  @filter = filter
300
251
  @if = check_conditionals(options[:if])
301
252
  @unless = check_conditionals(options[:unless])
253
+
254
+ compiled
302
255
  end
303
256
 
304
257
  def merge_conditional_options(chain, if_option:, unless_option:)
@@ -326,19 +279,26 @@ module ActiveSupport
326
279
  end
327
280
  end
328
281
 
282
+ def compiled
283
+ @compiled ||=
284
+ begin
285
+ user_conditions = conditions_lambdas
286
+ user_callback = CallTemplate.build(@filter, self)
287
+
288
+ case kind
289
+ when :before
290
+ Filters::Before.new(user_callback.make_lambda, user_conditions, chain_config, @filter, name)
291
+ when :after
292
+ Filters::After.new(user_callback.make_lambda, user_conditions, chain_config)
293
+ when :around
294
+ Filters::Around.new(user_callback, user_conditions)
295
+ end
296
+ end
297
+ end
298
+
329
299
  # Wraps code with filter
330
300
  def apply(callback_sequence)
331
- user_conditions = conditions_lambdas
332
- user_callback = CallTemplate.build(@filter, self)
333
-
334
- case kind
335
- when :before
336
- Filters::Before.build(callback_sequence, user_callback.make_lambda, user_conditions, chain_config, @filter, name)
337
- when :after
338
- Filters::After.build(callback_sequence, user_callback.make_lambda, user_conditions, chain_config)
339
- when :around
340
- callback_sequence.around(user_callback, user_conditions)
341
- end
301
+ compiled.apply(callback_sequence)
342
302
  end
343
303
 
344
304
  def current_scopes
@@ -365,14 +325,16 @@ module ActiveSupport
365
325
  end
366
326
 
367
327
  def conditions_lambdas
368
- @if.map { |c| CallTemplate.build(c, self).make_lambda } +
328
+ conditions =
329
+ @if.map { |c| CallTemplate.build(c, self).make_lambda } +
369
330
  @unless.map { |c| CallTemplate.build(c, self).inverted_lambda }
331
+ conditions.empty? ? EMPTY_ARRAY : conditions
370
332
  end
371
333
  end
372
334
 
373
335
  # A future invocation of user-supplied code (either as a callback,
374
336
  # or a condition filter).
375
- module CallTemplate # :nodoc:
337
+ module CallTemplate # :nodoc: all
376
338
  class MethodCall
377
339
  def initialize(method)
378
340
  @method_name = method
@@ -559,16 +521,18 @@ module ActiveSupport
559
521
  @call_template = call_template
560
522
  @user_conditions = user_conditions
561
523
 
562
- @before = []
563
- @after = []
524
+ @before = nil
525
+ @after = nil
564
526
  end
565
527
 
566
- def before(&before)
528
+ def before(before)
529
+ @before ||= []
567
530
  @before.unshift(before)
568
531
  self
569
532
  end
570
533
 
571
- def after(&after)
534
+ def after(after)
535
+ @after ||= []
572
536
  @after.push(after)
573
537
  self
574
538
  end
@@ -592,11 +556,11 @@ module ActiveSupport
592
556
  end
593
557
 
594
558
  def invoke_before(arg)
595
- @before.each { |b| b.call(arg) }
559
+ @before&.each { |b| b.call(arg) }
596
560
  end
597
561
 
598
562
  def invoke_after(arg)
599
- @after.each { |a| a.call(arg) }
563
+ @after&.each { |a| a.call(arg) }
600
564
  end
601
565
  end
602
566
 
@@ -612,7 +576,8 @@ module ActiveSupport
612
576
  terminator: default_terminator
613
577
  }.merge!(config)
614
578
  @chain = []
615
- @callbacks = nil
579
+ @all_callbacks = nil
580
+ @single_callbacks = {}
616
581
  @mutex = Mutex.new
617
582
  end
618
583
 
@@ -621,32 +586,45 @@ module ActiveSupport
621
586
  def empty?; @chain.empty?; end
622
587
 
623
588
  def insert(index, o)
624
- @callbacks = nil
589
+ @all_callbacks = nil
590
+ @single_callbacks.clear
625
591
  @chain.insert(index, o)
626
592
  end
627
593
 
628
594
  def delete(o)
629
- @callbacks = nil
595
+ @all_callbacks = nil
596
+ @single_callbacks.clear
630
597
  @chain.delete(o)
631
598
  end
632
599
 
633
600
  def clear
634
- @callbacks = nil
601
+ @all_callbacks = nil
602
+ @single_callbacks.clear
635
603
  @chain.clear
636
604
  self
637
605
  end
638
606
 
639
607
  def initialize_copy(other)
640
- @callbacks = nil
608
+ @all_callbacks = nil
609
+ @single_callbacks = {}
641
610
  @chain = other.chain.dup
642
611
  @mutex = Mutex.new
643
612
  end
644
613
 
645
- def compile
646
- @callbacks || @mutex.synchronize do
647
- final_sequence = CallbackSequence.new
648
- @callbacks ||= @chain.reverse.inject(final_sequence) do |callback_sequence, callback|
649
- callback.apply callback_sequence
614
+ def compile(type)
615
+ if type.nil?
616
+ @all_callbacks || @mutex.synchronize do
617
+ final_sequence = CallbackSequence.new
618
+ @all_callbacks ||= @chain.reverse.inject(final_sequence) do |callback_sequence, callback|
619
+ callback.apply(callback_sequence)
620
+ end
621
+ end
622
+ else
623
+ @single_callbacks[type] || @mutex.synchronize do
624
+ final_sequence = CallbackSequence.new
625
+ @single_callbacks[type] ||= @chain.reverse.inject(final_sequence) do |callback_sequence, callback|
626
+ type == callback.kind ? callback.apply(callback_sequence) : callback_sequence
627
+ end
650
628
  end
651
629
  end
652
630
  end
@@ -664,19 +642,22 @@ module ActiveSupport
664
642
 
665
643
  private
666
644
  def append_one(callback)
667
- @callbacks = nil
645
+ @all_callbacks = nil
646
+ @single_callbacks.clear
668
647
  remove_duplicates(callback)
669
648
  @chain.push(callback)
670
649
  end
671
650
 
672
651
  def prepend_one(callback)
673
- @callbacks = nil
652
+ @all_callbacks = nil
653
+ @single_callbacks.clear
674
654
  remove_duplicates(callback)
675
655
  @chain.unshift(callback)
676
656
  end
677
657
 
678
658
  def remove_duplicates(callback)
679
- @callbacks = nil
659
+ @all_callbacks = nil
660
+ @single_callbacks.clear
680
661
  @chain.delete_if { |c| callback.duplicates?(c) }
681
662
  end
682
663
 
@@ -703,7 +684,7 @@ module ActiveSupport
703
684
  # This is used internally to append, prepend and skip callbacks to the
704
685
  # CallbackChain.
705
686
  def __update_callbacks(name) # :nodoc:
706
- ([self] + self.descendants).reverse_each do |target|
687
+ self.descendants.prepend(self).reverse_each do |target|
707
688
  chain = target.get_callbacks name
708
689
  yield target, chain.dup
709
690
  end
@@ -723,7 +704,7 @@ module ActiveSupport
723
704
  #
724
705
  # The callback can be specified as a symbol naming an instance method; as a
725
706
  # proc, lambda, or block; or as an object that responds to a certain method
726
- # determined by the <tt>:scope</tt> argument to +define_callbacks+.
707
+ # determined by the <tt>:scope</tt> argument to #define_callbacks.
727
708
  #
728
709
  # If a proc, lambda, or block is given, its body is evaluated in the context
729
710
  # of the current object. It can also optionally accept the current object as
@@ -767,10 +748,13 @@ module ActiveSupport
767
748
  end
768
749
  end
769
750
 
770
- # Skip a previously set callback. Like +set_callback+, <tt>:if</tt> or
751
+ # Skip a previously set callback. Like #set_callback, <tt>:if</tt> or
771
752
  # <tt>:unless</tt> options may be passed in order to control when the
772
753
  # callback is skipped.
773
754
  #
755
+ # Note: this example uses +PersonRecord+ and +#saving_message+, which you
756
+ # can see defined here[rdoc-ref:ActiveSupport::Callbacks]
757
+ #
774
758
  # class Writer < PersonRecord
775
759
  # attr_accessor :age
776
760
  # skip_callback :save, :before, :saving_message, if: -> { age > 18 }
@@ -913,7 +897,7 @@ module ActiveSupport
913
897
  # <tt>!</tt>, <tt>?</tt> or <tt>=</tt>.
914
898
  #
915
899
  # Calling +define_callbacks+ multiple times with the same +names+ will
916
- # overwrite previous callbacks registered with +set_callback+.
900
+ # overwrite previous callbacks registered with #set_callback.
917
901
  def define_callbacks(*names)
918
902
  options = names.extract_options!
919
903
 
@@ -9,16 +9,19 @@ module ActiveSupport
9
9
  @cache = METHOD_CACHES[namespace]
10
10
  @sources = []
11
11
  @methods = {}
12
+ @canonical_methods = {}
12
13
  end
13
14
 
14
- def define_cached_method(name, as: name)
15
- name = name.to_sym
16
- as = as.to_sym
17
- @methods.fetch(name) do
18
- unless @cache.method_defined?(as)
15
+ def define_cached_method(canonical_name, as: nil)
16
+ canonical_name = canonical_name.to_sym
17
+ as = (as || canonical_name).to_sym
18
+
19
+ @methods.fetch(as) do
20
+ unless @cache.method_defined?(canonical_name) || @canonical_methods[canonical_name]
19
21
  yield @sources
20
22
  end
21
- @methods[name] = as
23
+ @canonical_methods[canonical_name] = true
24
+ @methods[as] = canonical_name
22
25
  end
23
26
  end
24
27
 
@@ -26,8 +29,10 @@ module ActiveSupport
26
29
  unless @sources.empty?
27
30
  @cache.module_eval("# frozen_string_literal: true\n" + @sources.join(";"), path, line)
28
31
  end
29
- @methods.each do |name, as|
30
- owner.define_method(name, @cache.instance_method(as))
32
+ @canonical_methods.clear
33
+
34
+ @methods.each do |as, canonical_name|
35
+ owner.define_method(as, @cache.instance_method(canonical_name))
31
36
  end
32
37
  end
33
38
  end
@@ -52,8 +57,8 @@ module ActiveSupport
52
57
  @namespaces = Hash.new { |h, k| h[k] = MethodSet.new(k) }
53
58
  end
54
59
 
55
- def define_cached_method(name, namespace:, as: name, &block)
56
- @namespaces[namespace].define_cached_method(name, as: as, &block)
60
+ def define_cached_method(canonical_name, namespace:, as: nil, &block)
61
+ @namespaces[namespace].define_cached_method(canonical_name, as: as, &block)
57
62
  end
58
63
 
59
64
  def execute
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveSupport
4
+ # = Active Support \Concern
5
+ #
4
6
  # A typical module looks like this:
5
7
  #
6
8
  # module M
@@ -16,7 +18,7 @@ module ActiveSupport
16
18
  # end
17
19
  # end
18
20
  #
19
- # By using <tt>ActiveSupport::Concern</tt> the above module could instead be
21
+ # By using +ActiveSupport::Concern+ the above module could instead be
20
22
  # written as:
21
23
  #
22
24
  # require "active_support/concern"
@@ -73,7 +75,7 @@ module ActiveSupport
73
75
  # end
74
76
  #
75
77
  # Unfortunately this won't work, since when +Foo+ is included, its <tt>base</tt>
76
- # is the +Bar+ module, not the +Host+ class. With <tt>ActiveSupport::Concern</tt>,
78
+ # is the +Bar+ module, not the +Host+ class. With +ActiveSupport::Concern+,
77
79
  # module dependencies are properly resolved:
78
80
  #
79
81
  # require "active_support/concern"
@@ -4,9 +4,7 @@ require "monitor"
4
4
 
5
5
  module ActiveSupport
6
6
  module Concurrency
7
- # A monitor that will permit dependency loading while blocked waiting for
8
- # the lock.
9
- class LoadInterlockAwareMonitor < Monitor
7
+ module LoadInterlockAwareMonitorMixin # :nodoc:
10
8
  EXCEPTION_NEVER = { Exception => :never }.freeze
11
9
  EXCEPTION_IMMEDIATE = { Exception => :immediate }.freeze
12
10
  private_constant :EXCEPTION_NEVER, :EXCEPTION_IMMEDIATE
@@ -29,5 +27,46 @@ module ActiveSupport
29
27
  end
30
28
  end
31
29
  end
30
+ # A monitor that will permit dependency loading while blocked waiting for
31
+ # the lock.
32
+ class LoadInterlockAwareMonitor < Monitor
33
+ include LoadInterlockAwareMonitorMixin
34
+ end
35
+
36
+ class ThreadLoadInterlockAwareMonitor # :nodoc:
37
+ prepend LoadInterlockAwareMonitorMixin
38
+
39
+ def initialize
40
+ @owner = nil
41
+ @count = 0
42
+ @mutex = Mutex.new
43
+ end
44
+
45
+ private
46
+ def mon_try_enter
47
+ if @owner != Thread.current
48
+ return false unless @mutex.try_lock
49
+ @owner = Thread.current
50
+ end
51
+ @count += 1
52
+ end
53
+
54
+ def mon_enter
55
+ @mutex.lock if @owner != Thread.current
56
+ @owner = Thread.current
57
+ @count += 1
58
+ end
59
+
60
+ def mon_exit
61
+ unless @owner == Thread.current
62
+ raise ThreadError, "current thread not owner"
63
+ end
64
+
65
+ @count -= 1
66
+ return unless @count == 0
67
+ @owner = nil
68
+ @mutex.unlock
69
+ end
70
+ end
32
71
  end
33
72
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module Concurrency
5
+ module NullLock # :nodoc:
6
+ extend self
7
+
8
+ def synchronize
9
+ yield
10
+ end
11
+ end
12
+ end
13
+ end
@@ -4,6 +4,8 @@ require "active_support/concern"
4
4
  require "active_support/ordered_options"
5
5
 
6
6
  module ActiveSupport
7
+ # = Active Support \Configurable
8
+ #
7
9
  # Configurable provides a <tt>config</tt> method to store and retrieve
8
10
  # configuration options as an OrderedOptions.
9
11
  module Configurable
@@ -125,6 +127,14 @@ module ActiveSupport
125
127
  end
126
128
  end
127
129
  private :config_accessor
130
+
131
+ private
132
+ def inherited(subclass)
133
+ super
134
+ subclass.class_eval do
135
+ @_config = nil
136
+ end
137
+ end
128
138
  end
129
139
 
130
140
  # Reads and writes attributes from a configuration OrderedOptions.
@@ -100,11 +100,10 @@ class Array
100
100
  collect(&:id).join(",")
101
101
  end
102
102
  else
103
- to_default_s
103
+ to_s
104
104
  end
105
105
  end
106
106
  alias_method :to_formatted_s, :to_fs
107
- alias_method :to_default_s, :to_s
108
107
 
109
108
  # Returns a string that represents the array in XML by invoking +to_xml+
110
109
  # on each element. Active Record collections delegate their representation
@@ -3,7 +3,6 @@
3
3
  require "active_support/core_ext/array/wrap"
4
4
  require "active_support/core_ext/array/access"
5
5
  require "active_support/core_ext/array/conversions"
6
- require "active_support/core_ext/array/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"]
7
6
  require "active_support/core_ext/array/extract"
8
7
  require "active_support/core_ext/array/extract_options"
9
8
  require "active_support/core_ext/array/grouping"