activesupport 5.1.7 → 7.0.4.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (279) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +259 -585
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -5
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/all.rb +2 -0
  7. data/lib/active_support/array_inquirer.rb +4 -2
  8. data/lib/active_support/backtrace_cleaner.rb +33 -5
  9. data/lib/active_support/benchmarkable.rb +5 -3
  10. data/lib/active_support/builder.rb +2 -0
  11. data/lib/active_support/cache/file_store.rb +50 -43
  12. data/lib/active_support/cache/mem_cache_store.rb +194 -67
  13. data/lib/active_support/cache/memory_store.rb +70 -34
  14. data/lib/active_support/cache/null_store.rb +18 -3
  15. data/lib/active_support/cache/redis_cache_store.rb +474 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +73 -50
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
  18. data/lib/active_support/cache.rb +556 -220
  19. data/lib/active_support/callbacks.rb +264 -159
  20. data/lib/active_support/code_generator.rb +65 -0
  21. data/lib/active_support/concern.rb +81 -8
  22. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +16 -0
  23. data/lib/active_support/concurrency/share_lock.rb +4 -3
  24. data/lib/active_support/configurable.rb +17 -16
  25. data/lib/active_support/configuration_file.rb +51 -0
  26. data/lib/active_support/core_ext/array/access.rb +18 -8
  27. data/lib/active_support/core_ext/array/conversions.rb +20 -17
  28. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  29. data/lib/active_support/core_ext/array/extract.rb +21 -0
  30. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  31. data/lib/active_support/core_ext/array/grouping.rb +8 -6
  32. data/lib/active_support/core_ext/array/inquiry.rb +4 -2
  33. data/lib/active_support/core_ext/array/wrap.rb +2 -0
  34. data/lib/active_support/core_ext/array.rb +4 -1
  35. data/lib/active_support/core_ext/benchmark.rb +4 -2
  36. data/lib/active_support/core_ext/big_decimal/conversions.rb +3 -1
  37. data/lib/active_support/core_ext/big_decimal.rb +2 -0
  38. data/lib/active_support/core_ext/class/attribute.rb +50 -47
  39. data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
  40. data/lib/active_support/core_ext/class/subclasses.rb +10 -24
  41. data/lib/active_support/core_ext/class.rb +2 -0
  42. data/lib/active_support/core_ext/date/acts_like.rb +2 -0
  43. data/lib/active_support/core_ext/date/blank.rb +3 -1
  44. data/lib/active_support/core_ext/date/calculations.rb +17 -14
  45. data/lib/active_support/core_ext/date/conversions.rb +24 -22
  46. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  47. data/lib/active_support/core_ext/date/zones.rb +2 -0
  48. data/lib/active_support/core_ext/date.rb +3 -0
  49. data/lib/active_support/core_ext/date_and_time/calculations.rb +65 -41
  50. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -1
  51. data/lib/active_support/core_ext/date_and_time/zones.rb +2 -1
  52. data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
  53. data/lib/active_support/core_ext/date_time/blank.rb +3 -1
  54. data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
  55. data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
  56. data/lib/active_support/core_ext/date_time/conversions.rb +15 -14
  57. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  58. data/lib/active_support/core_ext/date_time.rb +3 -0
  59. data/lib/active_support/core_ext/digest/uuid.rb +42 -14
  60. data/lib/active_support/core_ext/digest.rb +3 -0
  61. data/lib/active_support/core_ext/enumerable.rb +244 -72
  62. data/lib/active_support/core_ext/file/atomic.rb +6 -2
  63. data/lib/active_support/core_ext/file.rb +2 -0
  64. data/lib/active_support/core_ext/hash/conversions.rb +7 -6
  65. data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
  66. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  67. data/lib/active_support/core_ext/hash/except.rb +4 -2
  68. data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
  69. data/lib/active_support/core_ext/hash/keys.rb +4 -31
  70. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  71. data/lib/active_support/core_ext/hash/slice.rb +8 -29
  72. data/lib/active_support/core_ext/hash.rb +3 -2
  73. data/lib/active_support/core_ext/integer/inflections.rb +2 -0
  74. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  75. data/lib/active_support/core_ext/integer/time.rb +7 -14
  76. data/lib/active_support/core_ext/integer.rb +2 -0
  77. data/lib/active_support/core_ext/kernel/concern.rb +2 -0
  78. data/lib/active_support/core_ext/kernel/reporting.rb +6 -4
  79. data/lib/active_support/core_ext/kernel/singleton_class.rb +3 -1
  80. data/lib/active_support/core_ext/kernel.rb +2 -1
  81. data/lib/active_support/core_ext/load_error.rb +3 -8
  82. data/lib/active_support/core_ext/module/aliasing.rb +2 -0
  83. data/lib/active_support/core_ext/module/anonymous.rb +2 -0
  84. data/lib/active_support/core_ext/module/attr_internal.rb +4 -2
  85. data/lib/active_support/core_ext/module/attribute_accessors.rb +46 -56
  86. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +36 -27
  87. data/lib/active_support/core_ext/module/concerning.rb +15 -10
  88. data/lib/active_support/core_ext/module/delegation.rb +97 -58
  89. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  90. data/lib/active_support/core_ext/module/introspection.rb +18 -15
  91. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +5 -23
  93. data/lib/active_support/core_ext/module.rb +3 -1
  94. data/lib/active_support/core_ext/name_error.rb +30 -2
  95. data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +134 -129
  97. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +7 -15
  99. data/lib/active_support/core_ext/numeric.rb +3 -1
  100. data/lib/active_support/core_ext/object/acts_like.rb +41 -6
  101. data/lib/active_support/core_ext/object/blank.rb +15 -5
  102. data/lib/active_support/core_ext/object/conversions.rb +2 -0
  103. data/lib/active_support/core_ext/object/deep_dup.rb +3 -1
  104. data/lib/active_support/core_ext/object/duplicable.rb +16 -110
  105. data/lib/active_support/core_ext/object/inclusion.rb +2 -0
  106. data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
  107. data/lib/active_support/core_ext/object/json.rb +51 -26
  108. data/lib/active_support/core_ext/object/to_param.rb +2 -0
  109. data/lib/active_support/core_ext/object/to_query.rb +4 -2
  110. data/lib/active_support/core_ext/object/try.rb +26 -14
  111. data/lib/active_support/core_ext/object/with_options.rb +24 -3
  112. data/lib/active_support/core_ext/object.rb +2 -0
  113. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  114. data/lib/active_support/core_ext/pathname.rb +3 -0
  115. data/lib/active_support/core_ext/range/compare_range.rb +57 -0
  116. data/lib/active_support/core_ext/range/conversions.rb +35 -25
  117. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  118. data/lib/active_support/core_ext/range/each.rb +6 -3
  119. data/lib/active_support/core_ext/range/include_time_with_zone.rb +7 -0
  120. data/lib/active_support/core_ext/range/overlaps.rb +3 -1
  121. data/lib/active_support/core_ext/range.rb +4 -1
  122. data/lib/active_support/core_ext/regexp.rb +10 -5
  123. data/lib/active_support/core_ext/securerandom.rb +25 -3
  124. data/lib/active_support/core_ext/string/access.rb +7 -16
  125. data/lib/active_support/core_ext/string/behavior.rb +2 -0
  126. data/lib/active_support/core_ext/string/conversions.rb +5 -2
  127. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  128. data/lib/active_support/core_ext/string/filters.rb +44 -1
  129. data/lib/active_support/core_ext/string/indent.rb +2 -0
  130. data/lib/active_support/core_ext/string/inflections.rb +69 -16
  131. data/lib/active_support/core_ext/string/inquiry.rb +4 -1
  132. data/lib/active_support/core_ext/string/multibyte.rb +9 -4
  133. data/lib/active_support/core_ext/string/output_safety.rb +135 -27
  134. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  135. data/lib/active_support/core_ext/string/strip.rb +5 -1
  136. data/lib/active_support/core_ext/string/zones.rb +2 -0
  137. data/lib/active_support/core_ext/string.rb +2 -0
  138. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  139. data/lib/active_support/core_ext/symbol.rb +3 -0
  140. data/lib/active_support/core_ext/time/acts_like.rb +2 -0
  141. data/lib/active_support/core_ext/time/calculations.rb +81 -24
  142. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  143. data/lib/active_support/core_ext/time/conversions.rb +17 -12
  144. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  145. data/lib/active_support/core_ext/time/zones.rb +12 -25
  146. data/lib/active_support/core_ext/time.rb +3 -0
  147. data/lib/active_support/core_ext/uri.rb +4 -23
  148. data/lib/active_support/core_ext.rb +4 -1
  149. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  150. data/lib/active_support/current_attributes.rb +226 -0
  151. data/lib/active_support/dependencies/autoload.rb +2 -0
  152. data/lib/active_support/dependencies/interlock.rb +12 -18
  153. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  154. data/lib/active_support/dependencies.rb +59 -715
  155. data/lib/active_support/deprecation/behaviors.rb +48 -13
  156. data/lib/active_support/deprecation/constant_accessor.rb +4 -2
  157. data/lib/active_support/deprecation/disallowed.rb +56 -0
  158. data/lib/active_support/deprecation/instance_delegator.rb +2 -1
  159. data/lib/active_support/deprecation/method_wrappers.rb +29 -21
  160. data/lib/active_support/deprecation/proxy_wrappers.rb +34 -8
  161. data/lib/active_support/deprecation/reporting.rb +54 -9
  162. data/lib/active_support/deprecation.rb +10 -3
  163. data/lib/active_support/descendants_tracker.rb +192 -34
  164. data/lib/active_support/digest.rb +22 -0
  165. data/lib/active_support/duration/iso8601_parser.rb +9 -9
  166. data/lib/active_support/duration/iso8601_serializer.rb +29 -15
  167. data/lib/active_support/duration.rb +158 -72
  168. data/lib/active_support/encrypted_configuration.rb +56 -0
  169. data/lib/active_support/encrypted_file.rb +129 -0
  170. data/lib/active_support/environment_inquirer.rb +20 -0
  171. data/lib/active_support/error_reporter.rb +117 -0
  172. data/lib/active_support/evented_file_update_checker.rb +87 -122
  173. data/lib/active_support/execution_context/test_helper.rb +13 -0
  174. data/lib/active_support/execution_context.rb +53 -0
  175. data/lib/active_support/execution_wrapper.rb +46 -21
  176. data/lib/active_support/executor/test_helper.rb +7 -0
  177. data/lib/active_support/executor.rb +2 -0
  178. data/lib/active_support/file_update_checker.rb +2 -1
  179. data/lib/active_support/fork_tracker.rb +71 -0
  180. data/lib/active_support/gem_version.rb +7 -5
  181. data/lib/active_support/gzip.rb +2 -0
  182. data/lib/active_support/hash_with_indifferent_access.rb +126 -42
  183. data/lib/active_support/html_safe_translation.rb +43 -0
  184. data/lib/active_support/i18n.rb +5 -1
  185. data/lib/active_support/i18n_railtie.rb +19 -14
  186. data/lib/active_support/inflections.rb +2 -0
  187. data/lib/active_support/inflector/inflections.rb +41 -14
  188. data/lib/active_support/inflector/methods.rb +73 -87
  189. data/lib/active_support/inflector/transliterate.rb +56 -18
  190. data/lib/active_support/inflector.rb +2 -0
  191. data/lib/active_support/isolated_execution_state.rb +72 -0
  192. data/lib/active_support/json/decoding.rb +27 -26
  193. data/lib/active_support/json/encoding.rb +16 -6
  194. data/lib/active_support/json.rb +2 -0
  195. data/lib/active_support/key_generator.rb +25 -38
  196. data/lib/active_support/lazy_load_hooks.rb +35 -6
  197. data/lib/active_support/locale/en.rb +33 -0
  198. data/lib/active_support/locale/en.yml +8 -4
  199. data/lib/active_support/log_subscriber/test_helper.rb +4 -2
  200. data/lib/active_support/log_subscriber.rb +54 -13
  201. data/lib/active_support/logger.rb +4 -17
  202. data/lib/active_support/logger_silence.rb +13 -20
  203. data/lib/active_support/logger_thread_safe_level.rb +48 -10
  204. data/lib/active_support/message_encryptor.rb +111 -37
  205. data/lib/active_support/message_verifier.rb +124 -21
  206. data/lib/active_support/messages/metadata.rb +80 -0
  207. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  208. data/lib/active_support/messages/rotator.rb +57 -0
  209. data/lib/active_support/multibyte/chars.rb +19 -76
  210. data/lib/active_support/multibyte/unicode.rb +9 -331
  211. data/lib/active_support/multibyte.rb +3 -1
  212. data/lib/active_support/notifications/fanout.rb +165 -37
  213. data/lib/active_support/notifications/instrumenter.rb +92 -11
  214. data/lib/active_support/notifications.rb +96 -30
  215. data/lib/active_support/number_helper/number_converter.rb +8 -9
  216. data/lib/active_support/number_helper/number_to_currency_converter.rb +14 -12
  217. data/lib/active_support/number_helper/number_to_delimited_converter.rb +6 -3
  218. data/lib/active_support/number_helper/number_to_human_converter.rb +6 -3
  219. data/lib/active_support/number_helper/number_to_human_size_converter.rb +7 -4
  220. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  221. data/lib/active_support/number_helper/number_to_phone_converter.rb +6 -3
  222. data/lib/active_support/number_helper/number_to_rounded_converter.rb +14 -27
  223. data/lib/active_support/number_helper/rounding_helper.rb +16 -34
  224. data/lib/active_support/number_helper.rb +38 -12
  225. data/lib/active_support/option_merger.rb +19 -6
  226. data/lib/active_support/ordered_hash.rb +4 -2
  227. data/lib/active_support/ordered_options.rb +18 -6
  228. data/lib/active_support/parameter_filter.rb +138 -0
  229. data/lib/active_support/per_thread_registry.rb +8 -1
  230. data/lib/active_support/proxy_object.rb +2 -0
  231. data/lib/active_support/rails.rb +3 -10
  232. data/lib/active_support/railtie.rb +112 -11
  233. data/lib/active_support/reloader.rb +12 -11
  234. data/lib/active_support/rescuable.rb +19 -18
  235. data/lib/active_support/ruby_features.rb +7 -0
  236. data/lib/active_support/secure_compare_rotator.rb +51 -0
  237. data/lib/active_support/security_utils.rb +26 -15
  238. data/lib/active_support/string_inquirer.rb +4 -3
  239. data/lib/active_support/subscriber.rb +81 -42
  240. data/lib/active_support/tagged_logging.rb +45 -9
  241. data/lib/active_support/test_case.rb +86 -2
  242. data/lib/active_support/testing/assertions.rb +89 -21
  243. data/lib/active_support/testing/autorun.rb +2 -0
  244. data/lib/active_support/testing/constant_lookup.rb +2 -0
  245. data/lib/active_support/testing/declarative.rb +2 -0
  246. data/lib/active_support/testing/deprecation.rb +54 -2
  247. data/lib/active_support/testing/file_fixtures.rb +4 -0
  248. data/lib/active_support/testing/isolation.rb +6 -4
  249. data/lib/active_support/testing/method_call_assertions.rb +34 -5
  250. data/lib/active_support/testing/parallelization/server.rb +82 -0
  251. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  252. data/lib/active_support/testing/parallelization.rb +55 -0
  253. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  254. data/lib/active_support/testing/setup_and_teardown.rb +12 -7
  255. data/lib/active_support/testing/stream.rb +6 -7
  256. data/lib/active_support/testing/tagged_logging.rb +3 -1
  257. data/lib/active_support/testing/time_helpers.rb +91 -15
  258. data/lib/active_support/time.rb +2 -0
  259. data/lib/active_support/time_with_zone.rb +168 -56
  260. data/lib/active_support/values/time_zone.rb +85 -37
  261. data/lib/active_support/version.rb +3 -1
  262. data/lib/active_support/xml_mini/jdom.rb +6 -5
  263. data/lib/active_support/xml_mini/libxml.rb +9 -7
  264. data/lib/active_support/xml_mini/libxmlsax.rb +7 -5
  265. data/lib/active_support/xml_mini/nokogiri.rb +8 -6
  266. data/lib/active_support/xml_mini/nokogirisax.rb +6 -4
  267. data/lib/active_support/xml_mini/rexml.rb +13 -4
  268. data/lib/active_support/xml_mini.rb +10 -15
  269. data/lib/active_support.rb +30 -9
  270. metadata +76 -35
  271. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  272. data/lib/active_support/core_ext/hash/compact.rb +0 -27
  273. data/lib/active_support/core_ext/hash/transform_values.rb +0 -30
  274. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  275. data/lib/active_support/core_ext/marshal.rb +0 -22
  276. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  277. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
  278. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  279. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,11 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/concern"
2
4
  require "active_support/descendants_tracker"
3
5
  require "active_support/core_ext/array/extract_options"
4
6
  require "active_support/core_ext/class/attribute"
5
- require "active_support/core_ext/kernel/reporting"
6
- require "active_support/core_ext/kernel/singleton_class"
7
7
  require "active_support/core_ext/string/filters"
8
- require "active_support/deprecation"
8
+ require "active_support/core_ext/object/blank"
9
9
  require "thread"
10
10
 
11
11
  module ActiveSupport
@@ -16,16 +16,19 @@ module ActiveSupport
16
16
  # needing to override or redefine methods of the base class.
17
17
  #
18
18
  # Mixing in this module allows you to define the events in the object's
19
- # life cycle that will support callbacks (via +ClassMethods.define_callbacks+),
19
+ # life cycle that will support callbacks (via ClassMethods#define_callbacks),
20
20
  # set the instance methods, procs, or callback objects to be called (via
21
- # +ClassMethods.set_callback+), and run the installed callbacks at the
21
+ # ClassMethods#set_callback), and run the installed callbacks at the
22
22
  # appropriate times (via +run_callbacks+).
23
23
  #
24
+ # By default callbacks are halted by throwing +:abort+.
25
+ # See ClassMethods#define_callbacks for details.
26
+ #
24
27
  # Three kinds of callbacks are supported: before callbacks, run before a
25
28
  # certain event; after callbacks, run after the event; and around callbacks,
26
29
  # blocks that surround the event, triggering it when they yield. Callback code
27
30
  # can be contained in instance methods, procs or lambdas, or callback objects
28
- # that respond to certain predetermined methods. See +ClassMethods.set_callback+
31
+ # that respond to certain predetermined methods. See ClassMethods#set_callback
29
32
  # for details.
30
33
  #
31
34
  # class Record
@@ -62,8 +65,7 @@ module ActiveSupport
62
65
 
63
66
  included do
64
67
  extend ActiveSupport::DescendantsTracker
65
- class_attribute :__callbacks, instance_writer: false
66
- self.__callbacks ||= {}
68
+ class_attribute :__callbacks, instance_writer: false, default: {}
67
69
  end
68
70
 
69
71
  CALLBACK_FILTER_TYPES = [:before, :after, :around]
@@ -99,32 +101,6 @@ module ActiveSupport
99
101
  env = Filters::Environment.new(self, false, nil)
100
102
  next_sequence = callbacks.compile
101
103
 
102
- invoke_sequence = Proc.new do
103
- skipped = nil
104
- while true
105
- current = next_sequence
106
- current.invoke_before(env)
107
- if current.final?
108
- env.value = !env.halted && (!block_given? || yield)
109
- elsif current.skip?(env)
110
- (skipped ||= []) << current
111
- next_sequence = next_sequence.nested
112
- next
113
- else
114
- next_sequence = next_sequence.nested
115
- begin
116
- target, block, method, *arguments = current.expand_call_template(env, invoke_sequence)
117
- target.send(method, *arguments, &block)
118
- ensure
119
- next_sequence = current
120
- end
121
- end
122
- current.invoke_after(env)
123
- skipped.pop.invoke_after(env) while skipped && skipped.first
124
- break env.value
125
- end
126
- end
127
-
128
104
  # Common case: no 'around' callbacks defined
129
105
  if next_sequence.final?
130
106
  next_sequence.invoke_before(env)
@@ -132,17 +108,43 @@ module ActiveSupport
132
108
  next_sequence.invoke_after(env)
133
109
  env.value
134
110
  else
111
+ invoke_sequence = Proc.new do
112
+ skipped = nil
113
+
114
+ while true
115
+ current = next_sequence
116
+ current.invoke_before(env)
117
+ if current.final?
118
+ env.value = !env.halted && (!block_given? || yield)
119
+ elsif current.skip?(env)
120
+ (skipped ||= []) << current
121
+ next_sequence = next_sequence.nested
122
+ next
123
+ else
124
+ next_sequence = next_sequence.nested
125
+ begin
126
+ target, block, method, *arguments = current.expand_call_template(env, invoke_sequence)
127
+ target.send(method, *arguments, &block)
128
+ ensure
129
+ next_sequence = current
130
+ end
131
+ end
132
+ current.invoke_after(env)
133
+ skipped.pop.invoke_after(env) while skipped&.first
134
+ break env.value
135
+ end
136
+ end
137
+
135
138
  invoke_sequence.call
136
139
  end
137
140
  end
138
141
  end
139
142
 
140
143
  private
141
-
142
144
  # A hook invoked every time a before callback is halted.
143
145
  # This can be overridden in ActiveSupport::Callbacks implementors in order
144
146
  # to provide better debugging/logging.
145
- def halted_callback_hook(filter)
147
+ def halted_callback_hook(filter, name)
146
148
  end
147
149
 
148
150
  module Conditionals # :nodoc:
@@ -158,17 +160,17 @@ module ActiveSupport
158
160
  Environment = Struct.new(:target, :halted, :value)
159
161
 
160
162
  class Before
161
- def self.build(callback_sequence, user_callback, user_conditions, chain_config, filter)
163
+ def self.build(callback_sequence, user_callback, user_conditions, chain_config, filter, name)
162
164
  halted_lambda = chain_config[:terminator]
163
165
 
164
166
  if user_conditions.any?
165
- halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter)
167
+ halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter, name)
166
168
  else
167
- halting(callback_sequence, user_callback, halted_lambda, filter)
169
+ halting(callback_sequence, user_callback, halted_lambda, filter, name)
168
170
  end
169
171
  end
170
172
 
171
- def self.halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter)
173
+ def self.halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter, name)
172
174
  callback_sequence.before do |env|
173
175
  target = env.target
174
176
  value = env.value
@@ -178,7 +180,7 @@ module ActiveSupport
178
180
  result_lambda = -> { user_callback.call target, value }
179
181
  env.halted = halted_lambda.call(target, result_lambda)
180
182
  if env.halted
181
- target.send :halted_callback_hook, filter
183
+ target.send :halted_callback_hook, filter, name
182
184
  end
183
185
  end
184
186
 
@@ -187,7 +189,7 @@ module ActiveSupport
187
189
  end
188
190
  private_class_method :halting_and_conditional
189
191
 
190
- def self.halting(callback_sequence, user_callback, halted_lambda, filter)
192
+ def self.halting(callback_sequence, user_callback, halted_lambda, filter, name)
191
193
  callback_sequence.before do |env|
192
194
  target = env.target
193
195
  value = env.value
@@ -196,9 +198,8 @@ module ActiveSupport
196
198
  unless halted
197
199
  result_lambda = -> { user_callback.call target, value }
198
200
  env.halted = halted_lambda.call(target, result_lambda)
199
-
200
201
  if env.halted
201
- target.send :halted_callback_hook, filter
202
+ target.send :halted_callback_hook, filter, name
202
203
  end
203
204
  end
204
205
 
@@ -276,7 +277,7 @@ module ActiveSupport
276
277
  end
277
278
  end
278
279
 
279
- class Callback #:nodoc:#
280
+ class Callback # :nodoc:#
280
281
  def self.build(chain, filter, kind, options)
281
282
  if filter.is_a?(String)
282
283
  raise ArgumentError, <<-MSG.squish
@@ -289,21 +290,17 @@ module ActiveSupport
289
290
  end
290
291
 
291
292
  attr_accessor :kind, :name
292
- attr_reader :chain_config
293
+ attr_reader :chain_config, :filter
293
294
 
294
295
  def initialize(name, filter, kind, options, chain_config)
295
296
  @chain_config = chain_config
296
297
  @name = name
297
298
  @kind = kind
298
299
  @filter = filter
299
- @key = compute_identifier filter
300
- @if = Array(options[:if])
301
- @unless = Array(options[:unless])
300
+ @if = check_conditionals(options[:if])
301
+ @unless = check_conditionals(options[:unless])
302
302
  end
303
303
 
304
- def filter; @key; end
305
- def raw_filter; @filter; end
306
-
307
304
  def merge_conditional_options(chain, if_option:, unless_option:)
308
305
  options = {
309
306
  if: @if.dup,
@@ -322,7 +319,7 @@ module ActiveSupport
322
319
 
323
320
  def duplicates?(other)
324
321
  case @filter
325
- when Symbol, String
322
+ when Symbol
326
323
  matches?(other.kind, other.filter)
327
324
  else
328
325
  false
@@ -336,7 +333,7 @@ module ActiveSupport
336
333
 
337
334
  case kind
338
335
  when :before
339
- Filters::Before.build(callback_sequence, user_callback.make_lambda, user_conditions, chain_config, @filter)
336
+ Filters::Before.build(callback_sequence, user_callback.make_lambda, user_conditions, chain_config, @filter, name)
340
337
  when :after
341
338
  Filters::After.build(callback_sequence, user_callback.make_lambda, user_conditions, chain_config)
342
339
  when :around
@@ -349,13 +346,22 @@ module ActiveSupport
349
346
  end
350
347
 
351
348
  private
352
- def compute_identifier(filter)
353
- case filter
354
- when String, ::Proc
355
- filter.object_id
356
- else
357
- filter
349
+ EMPTY_ARRAY = [].freeze
350
+ private_constant :EMPTY_ARRAY
351
+
352
+ def check_conditionals(conditionals)
353
+ return EMPTY_ARRAY if conditionals.blank?
354
+
355
+ conditionals = Array(conditionals)
356
+ if conditionals.any?(String)
357
+ raise ArgumentError, <<-MSG.squish
358
+ Passing string to be evaluated in :if and :unless conditional
359
+ options is not supported. Pass a symbol for an instance method,
360
+ or a lambda, proc or block, instead.
361
+ MSG
358
362
  end
363
+
364
+ conditionals.freeze
359
365
  end
360
366
 
361
367
  def conditions_lambdas
@@ -366,67 +372,159 @@ module ActiveSupport
366
372
 
367
373
  # A future invocation of user-supplied code (either as a callback,
368
374
  # or a condition filter).
369
- class CallTemplate # :nodoc:
370
- def initialize(target, method, arguments, block)
371
- @override_target = target
372
- @method_name = method
373
- @arguments = arguments
374
- @override_block = block
375
+ module CallTemplate # :nodoc:
376
+ class MethodCall
377
+ def initialize(method)
378
+ @method_name = method
379
+ end
380
+
381
+ # Return the parts needed to make this call, with the given
382
+ # input values.
383
+ #
384
+ # Returns an array of the form:
385
+ #
386
+ # [target, block, method, *arguments]
387
+ #
388
+ # This array can be used as such:
389
+ #
390
+ # target.send(method, *arguments, &block)
391
+ #
392
+ # The actual invocation is left up to the caller to minimize
393
+ # call stack pollution.
394
+ def expand(target, value, block)
395
+ [target, block, @method_name]
396
+ end
397
+
398
+ def make_lambda
399
+ lambda do |target, value, &block|
400
+ target.send(@method_name, &block)
401
+ end
402
+ end
403
+
404
+ def inverted_lambda
405
+ lambda do |target, value, &block|
406
+ !target.send(@method_name, &block)
407
+ end
408
+ end
375
409
  end
376
410
 
377
- # Return the parts needed to make this call, with the given
378
- # input values.
379
- #
380
- # Returns an array of the form:
381
- #
382
- # [target, block, method, *arguments]
383
- #
384
- # This array can be used as such:
385
- #
386
- # target.send(method, *arguments, &block)
387
- #
388
- # The actual invocation is left up to the caller to minimize
389
- # call stack pollution.
390
- def expand(target, value, block)
391
- result = @arguments.map { |arg|
392
- case arg
393
- when :value; value
394
- when :target; target
395
- when :block; block || raise(ArgumentError)
411
+ class ObjectCall
412
+ def initialize(target, method)
413
+ @override_target = target
414
+ @method_name = method
415
+ end
416
+
417
+ def expand(target, value, block)
418
+ [@override_target || target, block, @method_name, target]
419
+ end
420
+
421
+ def make_lambda
422
+ lambda do |target, value, &block|
423
+ (@override_target || target).send(@method_name, target, &block)
396
424
  end
397
- }
425
+ end
426
+
427
+ def inverted_lambda
428
+ lambda do |target, value, &block|
429
+ !(@override_target || target).send(@method_name, target, &block)
430
+ end
431
+ end
432
+ end
433
+
434
+ class InstanceExec0
435
+ def initialize(block)
436
+ @override_block = block
437
+ end
438
+
439
+ def expand(target, value, block)
440
+ [target, @override_block, :instance_exec]
441
+ end
398
442
 
399
- result.unshift @method_name
400
- result.unshift @override_block || block
401
- result.unshift @override_target || target
443
+ def make_lambda
444
+ lambda do |target, value, &block|
445
+ target.instance_exec(&@override_block)
446
+ end
447
+ end
402
448
 
403
- # target, block, method, *arguments = result
404
- # target.send(method, *arguments, &block)
405
- result
449
+ def inverted_lambda
450
+ lambda do |target, value, &block|
451
+ !target.instance_exec(&@override_block)
452
+ end
453
+ end
406
454
  end
407
455
 
408
- # Return a lambda that will make this call when given the input
409
- # values.
410
- def make_lambda
411
- lambda do |target, value, &block|
412
- target, block, method, *arguments = expand(target, value, block)
413
- target.send(method, *arguments, &block)
456
+ class InstanceExec1
457
+ def initialize(block)
458
+ @override_block = block
459
+ end
460
+
461
+ def expand(target, value, block)
462
+ [target, @override_block, :instance_exec, target]
463
+ end
464
+
465
+ def make_lambda
466
+ lambda do |target, value, &block|
467
+ target.instance_exec(target, &@override_block)
468
+ end
469
+ end
470
+
471
+ def inverted_lambda
472
+ lambda do |target, value, &block|
473
+ !target.instance_exec(target, &@override_block)
474
+ end
475
+ end
476
+ end
477
+
478
+ class InstanceExec2
479
+ def initialize(block)
480
+ @override_block = block
481
+ end
482
+
483
+ def expand(target, value, block)
484
+ raise ArgumentError unless block
485
+ [target, @override_block || block, :instance_exec, target, block]
486
+ end
487
+
488
+ def make_lambda
489
+ lambda do |target, value, &block|
490
+ raise ArgumentError unless block
491
+ target.instance_exec(target, block, &@override_block)
492
+ end
493
+ end
494
+
495
+ def inverted_lambda
496
+ lambda do |target, value, &block|
497
+ raise ArgumentError unless block
498
+ !target.instance_exec(target, block, &@override_block)
499
+ end
414
500
  end
415
501
  end
416
502
 
417
- # Return a lambda that will make this call when given the input
418
- # values, but then return the boolean inverse of that result.
419
- def inverted_lambda
420
- lambda do |target, value, &block|
421
- target, block, method, *arguments = expand(target, value, block)
422
- ! target.send(method, *arguments, &block)
503
+ class ProcCall
504
+ def initialize(target)
505
+ @override_target = target
506
+ end
507
+
508
+ def expand(target, value, block)
509
+ [@override_target || target, block, :call, target, value]
510
+ end
511
+
512
+ def make_lambda
513
+ lambda do |target, value, &block|
514
+ (@override_target || target).call(target, value, &block)
515
+ end
516
+ end
517
+
518
+ def inverted_lambda
519
+ lambda do |target, value, &block|
520
+ !(@override_target || target).call(target, value, &block)
521
+ end
423
522
  end
424
523
  end
425
524
 
426
525
  # Filters support:
427
526
  #
428
527
  # Symbols:: A method to call.
429
- # Strings:: Some content to evaluate.
430
528
  # Procs:: A proc to call with the object.
431
529
  # Objects:: An object with a <tt>before_foo</tt> method on it to call.
432
530
  #
@@ -435,29 +533,21 @@ module ActiveSupport
435
533
  def self.build(filter, callback)
436
534
  case filter
437
535
  when Symbol
438
- new(nil, filter, [], nil)
439
- when String
440
- new(nil, :instance_exec, [:value], compile_lambda(filter))
536
+ MethodCall.new(filter)
441
537
  when Conditionals::Value
442
- new(filter, :call, [:target, :value], nil)
538
+ ProcCall.new(filter)
443
539
  when ::Proc
444
540
  if filter.arity > 1
445
- new(nil, :instance_exec, [:target, :block], filter)
541
+ InstanceExec2.new(filter)
446
542
  elsif filter.arity > 0
447
- new(nil, :instance_exec, [:target], filter)
543
+ InstanceExec1.new(filter)
448
544
  else
449
- new(nil, :instance_exec, [], filter)
545
+ InstanceExec0.new(filter)
450
546
  end
451
547
  else
452
- method_to_call = callback.current_scopes.join("_")
453
-
454
- new(filter, method_to_call, [:target], nil)
548
+ ObjectCall.new(filter, callback.current_scopes.join("_").to_sym)
455
549
  end
456
550
  end
457
-
458
- def self.compile_lambda(filter)
459
- eval("lambda { |value| #{filter} }")
460
- end
461
551
  end
462
552
 
463
553
  # Execute before and after filters in a sequence instead of
@@ -491,9 +581,7 @@ module ActiveSupport
491
581
  arg.halted || !@user_conditions.all? { |c| c.call(arg.target, arg.value) }
492
582
  end
493
583
 
494
- def nested
495
- @nested
496
- end
584
+ attr_reader :nested
497
585
 
498
586
  def final?
499
587
  !@call_template
@@ -512,8 +600,7 @@ module ActiveSupport
512
600
  end
513
601
  end
514
602
 
515
- # An Array with a compile method.
516
- class CallbackChain #:nodoc:#
603
+ class CallbackChain # :nodoc:
517
604
  include Enumerable
518
605
 
519
606
  attr_reader :name, :config
@@ -573,10 +660,9 @@ module ActiveSupport
573
660
  end
574
661
 
575
662
  protected
576
- def chain; @chain; end
663
+ attr_reader :chain
577
664
 
578
665
  private
579
-
580
666
  def append_one(callback)
581
667
  @callbacks = nil
582
668
  remove_duplicates(callback)
@@ -598,7 +684,7 @@ module ActiveSupport
598
684
  Proc.new do |target, result_lambda|
599
685
  terminate = true
600
686
  catch(:abort) do
601
- result_lambda.call if result_lambda.is_a?(Proc)
687
+ result_lambda.call
602
688
  terminate = false
603
689
  end
604
690
  terminate
@@ -616,8 +702,8 @@ module ActiveSupport
616
702
 
617
703
  # This is used internally to append, prepend and skip callbacks to the
618
704
  # CallbackChain.
619
- def __update_callbacks(name) #:nodoc:
620
- ([self] + ActiveSupport::DescendantsTracker.descendants(self)).reverse_each do |target|
705
+ def __update_callbacks(name) # :nodoc:
706
+ ([self] + self.descendants).reverse_each do |target|
621
707
  chain = target.get_callbacks name
622
708
  yield target, chain.dup
623
709
  end
@@ -651,26 +737,25 @@ module ActiveSupport
651
737
  #
652
738
  # ===== Options
653
739
  #
654
- # * <tt>:if</tt> - A symbol, a string (deprecated) or an array of symbols,
655
- # each naming an instance method or a proc; the callback will be called
656
- # only when they all return a true value.
657
- # * <tt>:unless</tt> - A symbol, a string (deprecated) or an array of symbols,
658
- # each naming an instance method or a proc; the callback will be called
659
- # only when they all return a false value.
740
+ # * <tt>:if</tt> - A symbol or an array of symbols, each naming an instance
741
+ # method or a proc; the callback will be called only when they all return
742
+ # a true value.
743
+ #
744
+ # If a proc is given, its body is evaluated in the context of the
745
+ # current object. It can also optionally accept the current object as
746
+ # an argument.
747
+ # * <tt>:unless</tt> - A symbol or an array of symbols, each naming an
748
+ # instance method or a proc; the callback will be called only when they
749
+ # all return a false value.
750
+ #
751
+ # If a proc is given, its body is evaluated in the context of the
752
+ # current object. It can also optionally accept the current object as
753
+ # an argument.
660
754
  # * <tt>:prepend</tt> - If +true+, the callback will be prepended to the
661
755
  # existing chain rather than appended.
662
756
  def set_callback(name, *filter_list, &block)
663
757
  type, filters, options = normalize_callback_params(filter_list, block)
664
758
 
665
- if options[:if].is_a?(String) || options[:unless].is_a?(String)
666
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
667
- Passing string to be evaluated in :if and :unless conditional
668
- options is deprecated and will be removed in Rails 5.2 without
669
- replacement. Pass a symbol for an instance method, or a lambda,
670
- proc or block, instead.
671
- MSG
672
- end
673
-
674
759
  self_chain = get_callbacks name
675
760
  mapped = filters.map do |filter|
676
761
  Callback.build(self_chain, filter, type, options)
@@ -686,22 +771,37 @@ module ActiveSupport
686
771
  # <tt>:unless</tt> options may be passed in order to control when the
687
772
  # callback is skipped.
688
773
  #
689
- # class Writer < Person
690
- # skip_callback :validate, :before, :check_membership, if: -> { age > 18 }
774
+ # class Writer < PersonRecord
775
+ # attr_accessor :age
776
+ # skip_callback :save, :before, :saving_message, if: -> { age > 18 }
691
777
  # end
692
778
  #
779
+ # When if option returns true, callback is skipped.
780
+ #
781
+ # writer = Writer.new
782
+ # writer.age = 20
783
+ # writer.save
784
+ #
785
+ # Output:
786
+ # - save
787
+ # saved
788
+ #
789
+ # When if option returns false, callback is NOT skipped.
790
+ #
791
+ # young_writer = Writer.new
792
+ # young_writer.age = 17
793
+ # young_writer.save
794
+ #
795
+ # Output:
796
+ # saving...
797
+ # - save
798
+ # saved
799
+ #
693
800
  # An <tt>ArgumentError</tt> will be raised if the callback has not
694
801
  # already been set (unless the <tt>:raise</tt> option is set to <tt>false</tt>).
695
802
  def skip_callback(name, *filter_list, &block)
696
803
  type, filters, options = normalize_callback_params(filter_list, block)
697
804
 
698
- if options[:if].is_a?(String) || options[:unless].is_a?(String)
699
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
700
- Passing string to :if and :unless conditional options is deprecated
701
- and will be removed in Rails 5.2 without replacement.
702
- MSG
703
- end
704
-
705
805
  options[:raise] = true unless options.key?(:raise)
706
806
 
707
807
  __update_callbacks(name) do |target, chain|
@@ -727,7 +827,7 @@ module ActiveSupport
727
827
  def reset_callbacks(name)
728
828
  callbacks = get_callbacks name
729
829
 
730
- ActiveSupport::DescendantsTracker.descendants(self).each do |target|
830
+ self.descendants.each do |target|
731
831
  chain = target.get_callbacks(name).dup
732
832
  callbacks.each { |c| chain.delete(c) }
733
833
  target.set_callbacks name, chain
@@ -760,8 +860,8 @@ module ActiveSupport
760
860
  # * <tt>:skip_after_callbacks_if_terminated</tt> - Determines if after
761
861
  # callbacks should be terminated by the <tt>:terminator</tt> option. By
762
862
  # default after callbacks are executed no matter if callback chain was
763
- # terminated or not. This option makes sense only when <tt>:terminator</tt>
764
- # option is specified.
863
+ # terminated or not. This option has no effect if <tt>:terminator</tt>
864
+ # option is set to +nil+.
765
865
  #
766
866
  # * <tt>:scope</tt> - Indicates which methods should be executed when an
767
867
  # object is used as a callback.
@@ -820,7 +920,9 @@ module ActiveSupport
820
920
  names.each do |name|
821
921
  name = name.to_sym
822
922
 
823
- set_callbacks name, CallbackChain.new(name, options)
923
+ ([self] + self.descendants).each do |target|
924
+ target.set_callbacks name, CallbackChain.new(name, options)
925
+ end
824
926
 
825
927
  module_eval <<-RUBY, __FILE__, __LINE__ + 1
826
928
  def _run_#{name}_callbacks(&block)
@@ -843,13 +945,16 @@ module ActiveSupport
843
945
  end
844
946
 
845
947
  protected
846
-
847
948
  def get_callbacks(name) # :nodoc:
848
949
  __callbacks[name.to_sym]
849
950
  end
850
951
 
851
952
  def set_callbacks(name, callbacks) # :nodoc:
852
- self.__callbacks = __callbacks.merge(name.to_sym => callbacks)
953
+ unless singleton_class.method_defined?(:__callbacks, false)
954
+ self.__callbacks = __callbacks.dup
955
+ end
956
+ self.__callbacks[name.to_sym] = callbacks
957
+ self.__callbacks
853
958
  end
854
959
  end
855
960
  end