activesupport 7.0.8 → 7.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (199) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +142 -428
  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/duplicable.rb +24 -15
  57. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  58. data/lib/active_support/core_ext/object/instance_variables.rb +4 -2
  59. data/lib/active_support/core_ext/object/json.rb +17 -7
  60. data/lib/active_support/core_ext/object/with.rb +46 -0
  61. data/lib/active_support/core_ext/object/with_options.rb +4 -4
  62. data/lib/active_support/core_ext/object.rb +1 -0
  63. data/lib/active_support/core_ext/pathname/blank.rb +20 -0
  64. data/lib/active_support/core_ext/pathname/existence.rb +2 -0
  65. data/lib/active_support/core_ext/pathname.rb +1 -0
  66. data/lib/active_support/core_ext/range/conversions.rb +28 -7
  67. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  68. data/lib/active_support/core_ext/range.rb +1 -2
  69. data/lib/active_support/core_ext/securerandom.rb +1 -5
  70. data/lib/active_support/core_ext/string/conversions.rb +1 -1
  71. data/lib/active_support/core_ext/string/filters.rb +21 -15
  72. data/lib/active_support/core_ext/string/indent.rb +1 -1
  73. data/lib/active_support/core_ext/string/inflections.rb +16 -5
  74. data/lib/active_support/core_ext/string/multibyte.rb +1 -1
  75. data/lib/active_support/core_ext/string/output_safety.rb +34 -177
  76. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  77. data/lib/active_support/core_ext/time/calculations.rb +36 -30
  78. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  79. data/lib/active_support/core_ext/time/conversions.rb +1 -3
  80. data/lib/active_support/core_ext/time/zones.rb +4 -4
  81. data/lib/active_support/core_ext/time.rb +0 -1
  82. data/lib/active_support/core_ext.rb +0 -1
  83. data/lib/active_support/current_attributes.rb +53 -46
  84. data/lib/active_support/deep_mergeable.rb +53 -0
  85. data/lib/active_support/delegation.rb +202 -0
  86. data/lib/active_support/dependencies/autoload.rb +9 -16
  87. data/lib/active_support/deprecation/behaviors.rb +65 -42
  88. data/lib/active_support/deprecation/constant_accessor.rb +47 -25
  89. data/lib/active_support/deprecation/deprecators.rb +104 -0
  90. data/lib/active_support/deprecation/disallowed.rb +3 -5
  91. data/lib/active_support/deprecation/method_wrappers.rb +6 -23
  92. data/lib/active_support/deprecation/proxy_wrappers.rb +34 -22
  93. data/lib/active_support/deprecation/reporting.rb +49 -27
  94. data/lib/active_support/deprecation.rb +39 -9
  95. data/lib/active_support/deprecator.rb +7 -0
  96. data/lib/active_support/descendants_tracker.rb +66 -172
  97. data/lib/active_support/duration/iso8601_parser.rb +2 -2
  98. data/lib/active_support/duration/iso8601_serializer.rb +1 -4
  99. data/lib/active_support/duration.rb +13 -7
  100. data/lib/active_support/encrypted_configuration.rb +30 -9
  101. data/lib/active_support/encrypted_file.rb +9 -4
  102. data/lib/active_support/environment_inquirer.rb +22 -2
  103. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  104. data/lib/active_support/error_reporter.rb +160 -36
  105. data/lib/active_support/evented_file_update_checker.rb +0 -1
  106. data/lib/active_support/execution_wrapper.rb +4 -5
  107. data/lib/active_support/file_update_checker.rb +5 -3
  108. data/lib/active_support/fork_tracker.rb +4 -32
  109. data/lib/active_support/gem_version.rb +3 -3
  110. data/lib/active_support/gzip.rb +2 -0
  111. data/lib/active_support/hash_with_indifferent_access.rb +41 -25
  112. data/lib/active_support/html_safe_translation.rb +19 -6
  113. data/lib/active_support/i18n.rb +1 -1
  114. data/lib/active_support/i18n_railtie.rb +20 -13
  115. data/lib/active_support/inflector/inflections.rb +2 -0
  116. data/lib/active_support/inflector/methods.rb +23 -11
  117. data/lib/active_support/inflector/transliterate.rb +3 -1
  118. data/lib/active_support/isolated_execution_state.rb +26 -22
  119. data/lib/active_support/json/decoding.rb +2 -1
  120. data/lib/active_support/json/encoding.rb +25 -43
  121. data/lib/active_support/key_generator.rb +9 -1
  122. data/lib/active_support/lazy_load_hooks.rb +6 -4
  123. data/lib/active_support/locale/en.yml +2 -0
  124. data/lib/active_support/log_subscriber.rb +74 -34
  125. data/lib/active_support/logger.rb +22 -60
  126. data/lib/active_support/logger_thread_safe_level.rb +10 -32
  127. data/lib/active_support/message_encryptor.rb +197 -53
  128. data/lib/active_support/message_encryptors.rb +141 -0
  129. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  130. data/lib/active_support/message_pack/extensions.rb +305 -0
  131. data/lib/active_support/message_pack/serializer.rb +63 -0
  132. data/lib/active_support/message_pack.rb +50 -0
  133. data/lib/active_support/message_verifier.rb +220 -89
  134. data/lib/active_support/message_verifiers.rb +135 -0
  135. data/lib/active_support/messages/codec.rb +65 -0
  136. data/lib/active_support/messages/metadata.rb +111 -45
  137. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  138. data/lib/active_support/messages/rotator.rb +34 -32
  139. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  140. data/lib/active_support/multibyte/chars.rb +4 -2
  141. data/lib/active_support/multibyte/unicode.rb +9 -37
  142. data/lib/active_support/notifications/fanout.rb +248 -87
  143. data/lib/active_support/notifications/instrumenter.rb +93 -25
  144. data/lib/active_support/notifications.rb +29 -28
  145. data/lib/active_support/number_helper/number_converter.rb +16 -7
  146. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -6
  147. data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -3
  148. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
  149. data/lib/active_support/number_helper.rb +379 -318
  150. data/lib/active_support/option_merger.rb +2 -2
  151. data/lib/active_support/ordered_hash.rb +3 -3
  152. data/lib/active_support/ordered_options.rb +67 -15
  153. data/lib/active_support/parameter_filter.rb +84 -69
  154. data/lib/active_support/proxy_object.rb +8 -3
  155. data/lib/active_support/railtie.rb +25 -20
  156. data/lib/active_support/reloader.rb +12 -4
  157. data/lib/active_support/rescuable.rb +2 -0
  158. data/lib/active_support/secure_compare_rotator.rb +16 -9
  159. data/lib/active_support/string_inquirer.rb +4 -2
  160. data/lib/active_support/subscriber.rb +10 -27
  161. data/lib/active_support/syntax_error_proxy.rb +60 -0
  162. data/lib/active_support/tagged_logging.rb +64 -25
  163. data/lib/active_support/test_case.rb +156 -7
  164. data/lib/active_support/testing/assertions.rb +28 -12
  165. data/lib/active_support/testing/autorun.rb +0 -2
  166. data/lib/active_support/testing/constant_stubbing.rb +54 -0
  167. data/lib/active_support/testing/deprecation.rb +20 -27
  168. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  169. data/lib/active_support/testing/isolation.rb +21 -9
  170. data/lib/active_support/testing/method_call_assertions.rb +7 -8
  171. data/lib/active_support/testing/parallelization/server.rb +3 -0
  172. data/lib/active_support/testing/parallelize_executor.rb +8 -3
  173. data/lib/active_support/testing/setup_and_teardown.rb +2 -0
  174. data/lib/active_support/testing/stream.rb +1 -1
  175. data/lib/active_support/testing/strict_warnings.rb +43 -0
  176. data/lib/active_support/testing/tests_without_assertions.rb +19 -0
  177. data/lib/active_support/testing/time_helpers.rb +38 -16
  178. data/lib/active_support/time_with_zone.rb +12 -18
  179. data/lib/active_support/values/time_zone.rb +25 -14
  180. data/lib/active_support/version.rb +1 -1
  181. data/lib/active_support/xml_mini/jdom.rb +3 -10
  182. data/lib/active_support/xml_mini/nokogiri.rb +1 -1
  183. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  184. data/lib/active_support/xml_mini/rexml.rb +1 -1
  185. data/lib/active_support/xml_mini.rb +12 -3
  186. data/lib/active_support.rb +15 -3
  187. metadata +145 -24
  188. data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
  189. data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -40
  190. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -36
  191. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
  192. data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -36
  193. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -5
  194. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  195. data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -73
  196. data/lib/active_support/core_ext/uri.rb +0 -5
  197. data/lib/active_support/deprecation/instance_delegator.rb +0 -38
  198. data/lib/active_support/per_thread_registry.rb +0 -65
  199. 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"