activesupport 6.0.6.1 → 7.1.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (245) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +865 -438
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -6
  5. data/lib/active_support/actionable_error.rb +4 -2
  6. data/lib/active_support/array_inquirer.rb +4 -2
  7. data/lib/active_support/backtrace_cleaner.rb +30 -10
  8. data/lib/active_support/benchmarkable.rb +4 -3
  9. data/lib/active_support/broadcast_logger.rb +250 -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 +53 -20
  14. data/lib/active_support/cache/mem_cache_store.rb +208 -63
  15. data/lib/active_support/cache/memory_store.rb +120 -38
  16. data/lib/active_support/cache/null_store.rb +16 -2
  17. data/lib/active_support/cache/redis_cache_store.rb +201 -208
  18. data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
  19. data/lib/active_support/cache/strategy/local_cache.rb +73 -66
  20. data/lib/active_support/cache.rb +539 -261
  21. data/lib/active_support/callbacks.rb +273 -142
  22. data/lib/active_support/code_generator.rb +65 -0
  23. data/lib/active_support/concern.rb +53 -7
  24. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +44 -7
  25. data/lib/active_support/concurrency/null_lock.rb +13 -0
  26. data/lib/active_support/concurrency/share_lock.rb +2 -2
  27. data/lib/active_support/configurable.rb +19 -6
  28. data/lib/active_support/configuration_file.rb +51 -0
  29. data/lib/active_support/core_ext/array/access.rb +1 -5
  30. data/lib/active_support/core_ext/array/conversions.rb +15 -13
  31. data/lib/active_support/core_ext/array/grouping.rb +6 -6
  32. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  33. data/lib/active_support/core_ext/benchmark.rb +2 -2
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  35. data/lib/active_support/core_ext/class/attribute.rb +34 -44
  36. data/lib/active_support/core_ext/class/subclasses.rb +19 -29
  37. data/lib/active_support/core_ext/date/blank.rb +1 -1
  38. data/lib/active_support/core_ext/date/calculations.rb +24 -9
  39. data/lib/active_support/core_ext/date/conversions.rb +18 -16
  40. data/lib/active_support/core_ext/date_and_time/calculations.rb +27 -4
  41. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  42. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  43. data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
  44. data/lib/active_support/core_ext/date_time/conversions.rb +19 -15
  45. data/lib/active_support/core_ext/digest/uuid.rb +30 -13
  46. data/lib/active_support/core_ext/enumerable.rb +146 -72
  47. data/lib/active_support/core_ext/erb/util.rb +196 -0
  48. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  49. data/lib/active_support/core_ext/hash/conversions.rb +3 -4
  50. data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
  51. data/lib/active_support/core_ext/hash/deep_transform_values.rb +4 -4
  52. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  53. data/lib/active_support/core_ext/hash/keys.rb +5 -5
  54. data/lib/active_support/core_ext/hash/slice.rb +3 -2
  55. data/lib/active_support/core_ext/integer/inflections.rb +12 -12
  56. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  57. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  58. data/lib/active_support/core_ext/load_error.rb +1 -1
  59. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  60. data/lib/active_support/core_ext/module/attribute_accessors.rb +31 -29
  61. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +51 -20
  62. data/lib/active_support/core_ext/module/concerning.rb +14 -8
  63. data/lib/active_support/core_ext/module/delegation.rb +75 -42
  64. data/lib/active_support/core_ext/module/deprecation.rb +15 -12
  65. data/lib/active_support/core_ext/module/introspection.rb +1 -26
  66. data/lib/active_support/core_ext/name_error.rb +23 -2
  67. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  68. data/lib/active_support/core_ext/numeric/conversions.rb +82 -73
  69. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  70. data/lib/active_support/core_ext/object/blank.rb +2 -2
  71. data/lib/active_support/core_ext/object/deep_dup.rb +17 -1
  72. data/lib/active_support/core_ext/object/duplicable.rb +15 -4
  73. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  74. data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
  75. data/lib/active_support/core_ext/object/json.rb +52 -28
  76. data/lib/active_support/core_ext/object/to_query.rb +2 -4
  77. data/lib/active_support/core_ext/object/try.rb +20 -20
  78. data/lib/active_support/core_ext/object/with.rb +44 -0
  79. data/lib/active_support/core_ext/object/with_options.rb +25 -6
  80. data/lib/active_support/core_ext/object.rb +1 -0
  81. data/lib/active_support/core_ext/pathname/blank.rb +16 -0
  82. data/lib/active_support/core_ext/pathname/existence.rb +23 -0
  83. data/lib/active_support/core_ext/pathname.rb +4 -0
  84. data/lib/active_support/core_ext/range/compare_range.rb +6 -25
  85. data/lib/active_support/core_ext/range/conversions.rb +34 -13
  86. data/lib/active_support/core_ext/range/each.rb +1 -1
  87. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  88. data/lib/active_support/core_ext/range.rb +1 -2
  89. data/lib/active_support/core_ext/regexp.rb +8 -1
  90. data/lib/active_support/core_ext/securerandom.rb +25 -13
  91. data/lib/active_support/core_ext/string/access.rb +5 -24
  92. data/lib/active_support/core_ext/string/conversions.rb +3 -2
  93. data/lib/active_support/core_ext/string/filters.rb +21 -15
  94. data/lib/active_support/core_ext/string/indent.rb +1 -1
  95. data/lib/active_support/core_ext/string/inflections.rb +51 -10
  96. data/lib/active_support/core_ext/string/inquiry.rb +2 -1
  97. data/lib/active_support/core_ext/string/multibyte.rb +2 -2
  98. data/lib/active_support/core_ext/string/output_safety.rb +85 -194
  99. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  100. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  101. data/lib/active_support/core_ext/symbol.rb +3 -0
  102. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  103. data/lib/active_support/core_ext/time/calculations.rb +46 -8
  104. data/lib/active_support/core_ext/time/conversions.rb +16 -13
  105. data/lib/active_support/core_ext/time/zones.rb +12 -28
  106. data/lib/active_support/core_ext.rb +2 -1
  107. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  108. data/lib/active_support/current_attributes.rb +54 -22
  109. data/lib/active_support/deep_mergeable.rb +53 -0
  110. data/lib/active_support/dependencies/autoload.rb +17 -12
  111. data/lib/active_support/dependencies/interlock.rb +10 -18
  112. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  113. data/lib/active_support/dependencies.rb +58 -769
  114. data/lib/active_support/deprecation/behaviors.rb +77 -38
  115. data/lib/active_support/deprecation/constant_accessor.rb +5 -4
  116. data/lib/active_support/deprecation/deprecators.rb +104 -0
  117. data/lib/active_support/deprecation/disallowed.rb +54 -0
  118. data/lib/active_support/deprecation/instance_delegator.rb +31 -5
  119. data/lib/active_support/deprecation/method_wrappers.rb +12 -28
  120. data/lib/active_support/deprecation/proxy_wrappers.rb +40 -25
  121. data/lib/active_support/deprecation/reporting.rb +76 -16
  122. data/lib/active_support/deprecation.rb +36 -4
  123. data/lib/active_support/deprecator.rb +7 -0
  124. data/lib/active_support/descendants_tracker.rb +150 -68
  125. data/lib/active_support/digest.rb +5 -3
  126. data/lib/active_support/duration/iso8601_parser.rb +3 -3
  127. data/lib/active_support/duration/iso8601_serializer.rb +24 -12
  128. data/lib/active_support/duration.rb +136 -56
  129. data/lib/active_support/encrypted_configuration.rb +72 -9
  130. data/lib/active_support/encrypted_file.rb +46 -13
  131. data/lib/active_support/environment_inquirer.rb +40 -0
  132. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  133. data/lib/active_support/error_reporter.rb +203 -0
  134. data/lib/active_support/evented_file_update_checker.rb +86 -137
  135. data/lib/active_support/execution_context/test_helper.rb +13 -0
  136. data/lib/active_support/execution_context.rb +53 -0
  137. data/lib/active_support/execution_wrapper.rb +31 -12
  138. data/lib/active_support/executor/test_helper.rb +7 -0
  139. data/lib/active_support/file_update_checker.rb +4 -2
  140. data/lib/active_support/fork_tracker.rb +79 -0
  141. data/lib/active_support/gem_version.rb +5 -5
  142. data/lib/active_support/gzip.rb +2 -0
  143. data/lib/active_support/hash_with_indifferent_access.rb +86 -42
  144. data/lib/active_support/html_safe_translation.rb +53 -0
  145. data/lib/active_support/i18n.rb +2 -1
  146. data/lib/active_support/i18n_railtie.rb +29 -27
  147. data/lib/active_support/inflector/inflections.rb +26 -9
  148. data/lib/active_support/inflector/methods.rb +54 -64
  149. data/lib/active_support/inflector/transliterate.rb +7 -5
  150. data/lib/active_support/isolated_execution_state.rb +76 -0
  151. data/lib/active_support/json/decoding.rb +6 -5
  152. data/lib/active_support/json/encoding.rb +31 -45
  153. data/lib/active_support/key_generator.rb +32 -7
  154. data/lib/active_support/lazy_load_hooks.rb +33 -7
  155. data/lib/active_support/locale/en.yml +10 -4
  156. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  157. data/lib/active_support/log_subscriber.rb +101 -32
  158. data/lib/active_support/logger.rb +9 -60
  159. data/lib/active_support/logger_silence.rb +2 -26
  160. data/lib/active_support/logger_thread_safe_level.rb +24 -25
  161. data/lib/active_support/message_encryptor.rb +205 -58
  162. data/lib/active_support/message_encryptors.rb +141 -0
  163. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  164. data/lib/active_support/message_pack/extensions.rb +292 -0
  165. data/lib/active_support/message_pack/serializer.rb +63 -0
  166. data/lib/active_support/message_pack.rb +50 -0
  167. data/lib/active_support/message_verifier.rb +237 -86
  168. data/lib/active_support/message_verifiers.rb +135 -0
  169. data/lib/active_support/messages/codec.rb +65 -0
  170. data/lib/active_support/messages/metadata.rb +112 -46
  171. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  172. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  173. data/lib/active_support/messages/rotator.rb +35 -32
  174. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  175. data/lib/active_support/multibyte/chars.rb +15 -52
  176. data/lib/active_support/multibyte/unicode.rb +8 -122
  177. data/lib/active_support/multibyte.rb +1 -1
  178. data/lib/active_support/notifications/fanout.rb +310 -105
  179. data/lib/active_support/notifications/instrumenter.rb +113 -48
  180. data/lib/active_support/notifications.rb +56 -29
  181. data/lib/active_support/number_helper/number_converter.rb +15 -8
  182. data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
  183. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
  184. data/lib/active_support/number_helper/number_to_human_converter.rb +1 -1
  185. data/lib/active_support/number_helper/number_to_human_size_converter.rb +5 -5
  186. data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
  187. data/lib/active_support/number_helper/number_to_rounded_converter.rb +9 -5
  188. data/lib/active_support/number_helper/rounding_helper.rb +12 -32
  189. data/lib/active_support/number_helper.rb +379 -304
  190. data/lib/active_support/option_merger.rb +11 -18
  191. data/lib/active_support/ordered_hash.rb +4 -4
  192. data/lib/active_support/ordered_options.rb +23 -3
  193. data/lib/active_support/parameter_filter.rb +104 -75
  194. data/lib/active_support/proxy_object.rb +2 -0
  195. data/lib/active_support/rails.rb +1 -4
  196. data/lib/active_support/railtie.rb +90 -6
  197. data/lib/active_support/reloader.rb +12 -4
  198. data/lib/active_support/rescuable.rb +18 -16
  199. data/lib/active_support/ruby_features.rb +7 -0
  200. data/lib/active_support/secure_compare_rotator.rb +58 -0
  201. data/lib/active_support/security_utils.rb +19 -12
  202. data/lib/active_support/string_inquirer.rb +5 -3
  203. data/lib/active_support/subscriber.rb +23 -47
  204. data/lib/active_support/syntax_error_proxy.rb +70 -0
  205. data/lib/active_support/tagged_logging.rb +84 -23
  206. data/lib/active_support/test_case.rb +166 -27
  207. data/lib/active_support/testing/assertions.rb +73 -20
  208. data/lib/active_support/testing/autorun.rb +0 -2
  209. data/lib/active_support/testing/constant_stubbing.rb +32 -0
  210. data/lib/active_support/testing/deprecation.rb +53 -2
  211. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  212. data/lib/active_support/testing/isolation.rb +30 -29
  213. data/lib/active_support/testing/method_call_assertions.rb +24 -11
  214. data/lib/active_support/testing/parallelization/server.rb +82 -0
  215. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  216. data/lib/active_support/testing/parallelization.rb +16 -95
  217. data/lib/active_support/testing/parallelize_executor.rb +81 -0
  218. data/lib/active_support/testing/stream.rb +4 -6
  219. data/lib/active_support/testing/strict_warnings.rb +39 -0
  220. data/lib/active_support/testing/tagged_logging.rb +1 -1
  221. data/lib/active_support/testing/time_helpers.rb +89 -19
  222. data/lib/active_support/time_with_zone.rb +105 -70
  223. data/lib/active_support/values/time_zone.rb +59 -26
  224. data/lib/active_support/version.rb +1 -1
  225. data/lib/active_support/xml_mini/jdom.rb +4 -11
  226. data/lib/active_support/xml_mini/libxml.rb +5 -5
  227. data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
  228. data/lib/active_support/xml_mini/nokogiri.rb +5 -5
  229. data/lib/active_support/xml_mini/nokogirisax.rb +2 -2
  230. data/lib/active_support/xml_mini/rexml.rb +9 -2
  231. data/lib/active_support/xml_mini.rb +7 -6
  232. data/lib/active_support.rb +40 -1
  233. metadata +127 -40
  234. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
  235. data/lib/active_support/core_ext/hash/compact.rb +0 -5
  236. data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
  237. data/lib/active_support/core_ext/marshal.rb +0 -24
  238. data/lib/active_support/core_ext/module/reachable.rb +0 -6
  239. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
  240. data/lib/active_support/core_ext/range/include_range.rb +0 -9
  241. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -23
  242. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  243. data/lib/active_support/core_ext/uri.rb +0 -25
  244. data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
  245. data/lib/active_support/per_thread_registry.rb +0 -60
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ class CodeGenerator # :nodoc:
5
+ class MethodSet
6
+ METHOD_CACHES = Hash.new { |h, k| h[k] = Module.new }
7
+
8
+ def initialize(namespace)
9
+ @cache = METHOD_CACHES[namespace]
10
+ @sources = []
11
+ @methods = {}
12
+ end
13
+
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)
19
+ yield @sources
20
+ end
21
+ @methods[name] = as
22
+ end
23
+ end
24
+
25
+ def apply(owner, path, line)
26
+ unless @sources.empty?
27
+ @cache.module_eval("# frozen_string_literal: true\n" + @sources.join(";"), path, line)
28
+ end
29
+ @methods.each do |name, as|
30
+ owner.define_method(name, @cache.instance_method(as))
31
+ end
32
+ end
33
+ end
34
+
35
+ class << self
36
+ def batch(owner, path, line)
37
+ if owner.is_a?(CodeGenerator)
38
+ yield owner
39
+ else
40
+ instance = new(owner, path, line)
41
+ result = yield instance
42
+ instance.execute
43
+ result
44
+ end
45
+ end
46
+ end
47
+
48
+ def initialize(owner, path, line)
49
+ @owner = owner
50
+ @path = path
51
+ @line = line
52
+ @namespaces = Hash.new { |h, k| h[k] = MethodSet.new(k) }
53
+ end
54
+
55
+ def define_cached_method(name, namespace:, as: name, &block)
56
+ @namespaces[namespace].define_cached_method(name, as: as, &block)
57
+ end
58
+
59
+ def execute
60
+ @namespaces.each_value do |method_set|
61
+ method_set.apply(@owner, @path, @line - 1)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -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,10 +18,10 @@ 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
- # require 'active_support/concern'
24
+ # require "active_support/concern"
23
25
  #
24
26
  # module M
25
27
  # extend ActiveSupport::Concern
@@ -73,10 +75,10 @@ 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
- # require 'active_support/concern'
81
+ # require "active_support/concern"
80
82
  #
81
83
  # module Foo
82
84
  # extend ActiveSupport::Concern
@@ -99,18 +101,32 @@ module ActiveSupport
99
101
  # class Host
100
102
  # include Bar # It works, now Bar takes care of its dependencies
101
103
  # end
104
+ #
105
+ # === Prepending concerns
106
+ #
107
+ # Just like <tt>include</tt>, concerns also support <tt>prepend</tt> with a corresponding
108
+ # <tt>prepended do</tt> callback. <tt>module ClassMethods</tt> or <tt>class_methods do</tt> are
109
+ # prepended as well.
110
+ #
111
+ # <tt>prepend</tt> is also used for any dependencies.
102
112
  module Concern
103
- class MultipleIncludedBlocks < StandardError #:nodoc:
113
+ class MultipleIncludedBlocks < StandardError # :nodoc:
104
114
  def initialize
105
115
  super "Cannot define multiple 'included' blocks for a Concern"
106
116
  end
107
117
  end
108
118
 
109
- def self.extended(base) #:nodoc:
119
+ class MultiplePrependBlocks < StandardError # :nodoc:
120
+ def initialize
121
+ super "Cannot define multiple 'prepended' blocks for a Concern"
122
+ end
123
+ end
124
+
125
+ def self.extended(base) # :nodoc:
110
126
  base.instance_variable_set(:@_dependencies, [])
111
127
  end
112
128
 
113
- def append_features(base) #:nodoc:
129
+ def append_features(base) # :nodoc:
114
130
  if base.instance_variable_defined?(:@_dependencies)
115
131
  base.instance_variable_get(:@_dependencies) << self
116
132
  false
@@ -123,6 +139,19 @@ module ActiveSupport
123
139
  end
124
140
  end
125
141
 
142
+ def prepend_features(base) # :nodoc:
143
+ if base.instance_variable_defined?(:@_dependencies)
144
+ base.instance_variable_get(:@_dependencies).unshift self
145
+ false
146
+ else
147
+ return false if base < self
148
+ @_dependencies.each { |dep| base.prepend(dep) }
149
+ super
150
+ base.singleton_class.prepend const_get(:ClassMethods) if const_defined?(:ClassMethods)
151
+ base.class_eval(&@_prepended_block) if instance_variable_defined?(:@_prepended_block)
152
+ end
153
+ end
154
+
126
155
  # Evaluate given block in context of base class,
127
156
  # so that you can write class macros here.
128
157
  # When you define more than one +included+ block, it raises an exception.
@@ -140,6 +169,23 @@ module ActiveSupport
140
169
  end
141
170
  end
142
171
 
172
+ # Evaluate given block in context of base class,
173
+ # so that you can write class macros here.
174
+ # When you define more than one +prepended+ block, it raises an exception.
175
+ def prepended(base = nil, &block)
176
+ if base.nil?
177
+ if instance_variable_defined?(:@_prepended_block)
178
+ if @_prepended_block.source_location != block.source_location
179
+ raise MultiplePrependBlocks
180
+ end
181
+ else
182
+ @_prepended_block = block
183
+ end
184
+ else
185
+ super
186
+ end
187
+ end
188
+
143
189
  # Define class methods from given block.
144
190
  # You can define private class methods as well.
145
191
  #
@@ -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
@@ -17,19 +15,58 @@ module ActiveSupport
17
15
  ActiveSupport::Dependencies.interlock.permit_concurrent_loads { super }
18
16
  end
19
17
 
20
- def synchronize
18
+ def synchronize(&block)
21
19
  Thread.handle_interrupt(EXCEPTION_NEVER) do
22
20
  mon_enter
23
21
 
24
22
  begin
25
- Thread.handle_interrupt(EXCEPTION_IMMEDIATE) do
26
- yield
27
- end
23
+ Thread.handle_interrupt(EXCEPTION_IMMEDIATE, &block)
28
24
  ensure
29
25
  mon_exit
30
26
  end
31
27
  end
32
28
  end
33
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
34
71
  end
35
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
@@ -215,9 +215,9 @@ module ActiveSupport
215
215
  @waiting.any? { |t, (p, _)| compatible.include?(p) && @waiting.all? { |t2, (_, c2)| t == t2 || c2.include?(p) } }
216
216
  end
217
217
 
218
- def wait_for(method)
218
+ def wait_for(method, &block)
219
219
  @sleeping[Thread.current] = method
220
- @cv.wait_while { yield }
220
+ @cv.wait_while(&block)
221
221
  ensure
222
222
  @sleeping.delete Thread.current
223
223
  end
@@ -4,8 +4,10 @@ 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
- # configuration options as an <tt>OrderedHash</tt>.
10
+ # configuration options as an OrderedOptions.
9
11
  module Configurable
10
12
  extend ActiveSupport::Concern
11
13
 
@@ -94,17 +96,19 @@ module ActiveSupport
94
96
  # User.new.allowed_access = true # => NoMethodError
95
97
  # User.new.allowed_access # => NoMethodError
96
98
  #
97
- # Also you can pass a block to set up the attribute with a default value.
99
+ # Also you can pass <tt>default</tt> or a block to set up the attribute with a default value.
98
100
  #
99
101
  # class User
100
102
  # include ActiveSupport::Configurable
103
+ # config_accessor :allowed_access, default: false
101
104
  # config_accessor :hair_colors do
102
105
  # [:brown, :black, :blonde, :red]
103
106
  # end
104
107
  # end
105
108
  #
109
+ # User.allowed_access # => false
106
110
  # User.hair_colors # => [:brown, :black, :blonde, :red]
107
- def config_accessor(*names, instance_reader: true, instance_writer: true, instance_accessor: true) # :doc:
111
+ def config_accessor(*names, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil) # :doc:
108
112
  names.each do |name|
109
113
  raise NameError.new("invalid config attribute name") unless /\A[_A-Za-z]\w*\z/.match?(name)
110
114
 
@@ -118,15 +122,24 @@ module ActiveSupport
118
122
  class_eval reader, __FILE__, reader_line if instance_reader
119
123
  class_eval writer, __FILE__, writer_line if instance_writer
120
124
  end
121
- send("#{name}=", yield) if block_given?
125
+
126
+ send("#{name}=", block_given? ? yield : default)
122
127
  end
123
128
  end
124
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
125
138
  end
126
139
 
127
- # Reads and writes attributes from a configuration <tt>OrderedHash</tt>.
140
+ # Reads and writes attributes from a configuration OrderedOptions.
128
141
  #
129
- # require 'active_support/configurable'
142
+ # require "active_support/configurable"
130
143
  #
131
144
  # class User
132
145
  # include ActiveSupport::Configurable
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ # Reads a YAML configuration file, evaluating any ERB, then
5
+ # parsing the resulting YAML.
6
+ #
7
+ # Warns in case of YAML confusing characters, like invisible
8
+ # non-breaking spaces.
9
+ class ConfigurationFile # :nodoc:
10
+ class FormatError < StandardError; end
11
+
12
+ def initialize(content_path)
13
+ @content_path = content_path.to_s
14
+ @content = read content_path
15
+ end
16
+
17
+ def self.parse(content_path, **options)
18
+ new(content_path).parse(**options)
19
+ end
20
+
21
+ def parse(context: nil, **options)
22
+ source = render(context)
23
+ if YAML.respond_to?(:unsafe_load)
24
+ YAML.unsafe_load(source, **options) || {}
25
+ else
26
+ YAML.load(source, **options) || {}
27
+ end
28
+ rescue Psych::SyntaxError => error
29
+ raise "YAML syntax error occurred while parsing #{@content_path}. " \
30
+ "Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
31
+ "Error: #{error.message}"
32
+ end
33
+
34
+ private
35
+ def read(content_path)
36
+ require "yaml"
37
+ require "erb"
38
+
39
+ File.read(content_path).tap do |content|
40
+ if content.include?("\u00A0")
41
+ warn "#{content_path} contains invisible non-breaking spaces, you may want to remove those"
42
+ end
43
+ end
44
+ end
45
+
46
+ def render(context)
47
+ erb = ERB.new(@content).tap { |e| e.filename = @content_path }
48
+ context ? erb.result(context) : erb.result
49
+ end
50
+ end
51
+ end
@@ -47,11 +47,7 @@ class Array
47
47
  def excluding(*elements)
48
48
  self - elements.flatten(1)
49
49
  end
50
-
51
- # Alias for #excluding.
52
- def without(*elements)
53
- excluding(*elements)
54
- end
50
+ alias :without :excluding
55
51
 
56
52
  # Equal to <tt>self[1]</tt>.
57
53
  #
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/xml_mini"
4
3
  require "active_support/core_ext/hash/keys"
5
4
  require "active_support/core_ext/string/inflections"
6
5
  require "active_support/core_ext/object/to_param"
@@ -16,12 +15,12 @@ class Array
16
15
  #
17
16
  # ==== Options
18
17
  #
19
- # * <tt>:words_connector</tt> - The sign or word used to join the elements
20
- # in arrays with two or more elements (default: ", ").
21
- # * <tt>:two_words_connector</tt> - The sign or word used to join the elements
22
- # in arrays with two elements (default: " and ").
18
+ # * <tt>:words_connector</tt> - The sign or word used to join all but the last
19
+ # element in arrays with three or more elements (default: ", ").
23
20
  # * <tt>:last_word_connector</tt> - The sign or word used to join the last element
24
21
  # in arrays with three or more elements (default: ", and ").
22
+ # * <tt>:two_words_connector</tt> - The sign or word used to join the elements
23
+ # in arrays with two elements (default: " and ").
25
24
  # * <tt>:locale</tt> - If +i18n+ is available, you can set a locale and use
26
25
  # the connector options defined on the 'support.array' namespace in the
27
26
  # corresponding dictionary file.
@@ -66,7 +65,7 @@ class Array
66
65
  two_words_connector: " and ",
67
66
  last_word_connector: ", and "
68
67
  }
69
- if defined?(I18n)
68
+ if options[:locale] != false && defined?(I18n)
70
69
  i18n_connectors = I18n.translate(:'support.array', locale: options[:locale], default: {})
71
70
  default_connectors.merge!(i18n_connectors)
72
71
  end
@@ -87,10 +86,12 @@ class Array
87
86
  # Extends <tt>Array#to_s</tt> to convert a collection of elements into a
88
87
  # comma separated id list if <tt>:db</tt> argument is given as the format.
89
88
  #
90
- # Blog.all.to_formatted_s(:db) # => "1,2,3"
91
- # Blog.none.to_formatted_s(:db) # => "null"
92
- # [1,2].to_formatted_s # => "[1, 2]"
93
- def to_formatted_s(format = :default)
89
+ # This method is aliased to <tt>to_formatted_s</tt>.
90
+ #
91
+ # Blog.all.to_fs(:db) # => "1,2,3"
92
+ # Blog.none.to_fs(:db) # => "null"
93
+ # [1,2].to_fs # => "[1, 2]"
94
+ def to_fs(format = :default)
94
95
  case format
95
96
  when :db
96
97
  if empty?
@@ -99,11 +100,12 @@ class Array
99
100
  collect(&:id).join(",")
100
101
  end
101
102
  else
102
- to_default_s
103
+ to_s
103
104
  end
104
105
  end
106
+ alias_method :to_formatted_s, :to_fs
105
107
  alias_method :to_default_s, :to_s
106
- alias_method :to_s, :to_formatted_s
108
+ deprecate to_default_s: :to_s, deprecator: ActiveSupport.deprecator
107
109
 
108
110
  # Returns a string that represents the array in XML by invoking +to_xml+
109
111
  # on each element. Active Record collections delegate their representation
@@ -187,7 +189,7 @@ class Array
187
189
  options[:indent] ||= 2
188
190
  options[:builder] ||= Builder::XmlMarkup.new(indent: options[:indent])
189
191
  options[:root] ||= \
190
- if first.class != Hash && all? { |e| e.is_a?(first.class) }
192
+ if first.class != Hash && all?(first.class)
191
193
  underscored = ActiveSupport::Inflector.underscore(first.class.name)
192
194
  ActiveSupport::Inflector.pluralize(underscored).tr("/", "_")
193
195
  else
@@ -19,7 +19,7 @@ class Array
19
19
  # ["1", "2"]
20
20
  # ["3", "4"]
21
21
  # ["5"]
22
- def in_groups_of(number, fill_with = nil)
22
+ def in_groups_of(number, fill_with = nil, &block)
23
23
  if number.to_i <= 0
24
24
  raise ArgumentError,
25
25
  "Group size must be a positive integer, was #{number.inspect}"
@@ -36,7 +36,7 @@ class Array
36
36
  end
37
37
 
38
38
  if block_given?
39
- collection.each_slice(number) { |slice| yield(slice) }
39
+ collection.each_slice(number, &block)
40
40
  else
41
41
  collection.each_slice(number).to_a
42
42
  end
@@ -59,7 +59,7 @@ class Array
59
59
  # ["1", "2", "3"]
60
60
  # ["4", "5"]
61
61
  # ["6", "7"]
62
- def in_groups(number, fill_with = nil)
62
+ def in_groups(number, fill_with = nil, &block)
63
63
  # size.div number gives minor group size;
64
64
  # size % number gives how many objects need extra accommodation;
65
65
  # each group hold either division or division + 1 items.
@@ -79,7 +79,7 @@ class Array
79
79
  end
80
80
 
81
81
  if block_given?
82
- groups.each { |g| yield(g) }
82
+ groups.each(&block)
83
83
  else
84
84
  groups
85
85
  end
@@ -90,11 +90,11 @@ class Array
90
90
  #
91
91
  # [1, 2, 3, 4, 5].split(3) # => [[1, 2], [4, 5]]
92
92
  # (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
93
- def split(value = nil)
93
+ def split(value = nil, &block)
94
94
  arr = dup
95
95
  result = []
96
96
  if block_given?
97
- while (idx = arr.index { |i| yield i })
97
+ while (idx = arr.index(&block))
98
98
  result << arr.shift(idx)
99
99
  arr.shift
100
100
  end
@@ -3,8 +3,8 @@
3
3
  require "active_support/array_inquirer"
4
4
 
5
5
  class Array
6
- # Wraps the array in an +ArrayInquirer+ object, which gives a friendlier way
7
- # to check its string-like contents.
6
+ # Wraps the array in an ActiveSupport::ArrayInquirer object, which gives a
7
+ # friendlier way to check its string-like contents.
8
8
  #
9
9
  # pets = [:cat, :dog].inquiry
10
10
  #
@@ -10,7 +10,7 @@ class << Benchmark
10
10
  #
11
11
  # Benchmark.ms { User.all }
12
12
  # # => 0.074
13
- def ms
14
- 1000 * realtime { yield }
13
+ def ms(&block)
14
+ 1000 * realtime(&block)
15
15
  end
16
16
  end
@@ -4,7 +4,7 @@ require "bigdecimal"
4
4
  require "bigdecimal/util"
5
5
 
6
6
  module ActiveSupport
7
- module BigDecimalWithDefaultFormat #:nodoc:
7
+ module BigDecimalWithDefaultFormat # :nodoc:
8
8
  def to_s(format = "F")
9
9
  super(format)
10
10
  end
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/kernel/singleton_class"
4
3
  require "active_support/core_ext/module/redefine_method"
5
- require "active_support/core_ext/array/extract_options"
6
4
 
7
5
  class Class
8
6
  # Declare a class-level attribute whose value is inheritable by subclasses.
@@ -84,58 +82,50 @@ class Class
84
82
  # To set a default value for the attribute, pass <tt>default:</tt>, like so:
85
83
  #
86
84
  # class_attribute :settings, default: {}
87
- def class_attribute(
88
- *attrs,
89
- instance_accessor: true,
90
- instance_reader: instance_accessor,
91
- instance_writer: instance_accessor,
92
- instance_predicate: true,
93
- default: nil
94
- )
95
- attrs.each do |name|
96
- singleton_class.silence_redefinition_of_method(name)
97
- define_singleton_method(name) { default }
98
-
99
- singleton_class.silence_redefinition_of_method("#{name}?")
100
- define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate
85
+ def class_attribute(*attrs, instance_accessor: true,
86
+ instance_reader: instance_accessor, instance_writer: instance_accessor, instance_predicate: true, default: nil)
101
87
 
102
- ivar = "@#{name}".to_sym
88
+ class_methods, methods = [], []
89
+ attrs.each do |name|
90
+ unless name.is_a?(Symbol) || name.is_a?(String)
91
+ raise TypeError, "#{name.inspect} is not a symbol nor a string"
92
+ end
103
93
 
104
- singleton_class.silence_redefinition_of_method("#{name}=")
105
- define_singleton_method("#{name}=") do |val|
106
- redefine_singleton_method(name) { val }
94
+ class_methods << <<~RUBY # In case the method exists and is not public
95
+ silence_redefinition_of_method def #{name}
96
+ end
97
+ RUBY
107
98
 
108
- if singleton_class?
109
- class_eval do
110
- redefine_method(name) do
111
- if instance_variable_defined? ivar
112
- instance_variable_get ivar
113
- else
114
- singleton_class.send name
115
- end
116
- end
117
- end
99
+ methods << <<~RUBY if instance_reader
100
+ silence_redefinition_of_method def #{name}
101
+ defined?(@#{name}) ? @#{name} : self.class.#{name}
118
102
  end
119
- val
120
- end
103
+ RUBY
121
104
 
122
- if instance_reader
123
- redefine_method(name) do
124
- if instance_variable_defined?(ivar)
125
- instance_variable_get ivar
126
- else
127
- self.class.public_send name
128
- end
105
+ class_methods << <<~RUBY
106
+ silence_redefinition_of_method def #{name}=(value)
107
+ redefine_method(:#{name}) { value } if singleton_class?
108
+ redefine_singleton_method(:#{name}) { value }
109
+ value
129
110
  end
111
+ RUBY
130
112
 
131
- redefine_method("#{name}?") { !!public_send(name) } if instance_predicate
132
- end
113
+ methods << <<~RUBY if instance_writer
114
+ silence_redefinition_of_method(:#{name}=)
115
+ attr_writer :#{name}
116
+ RUBY
133
117
 
134
- if instance_writer
135
- redefine_method("#{name}=") do |val|
136
- instance_variable_set ivar, val
118
+ if instance_predicate
119
+ class_methods << "silence_redefinition_of_method def #{name}?; !!self.#{name}; end"
120
+ if instance_reader
121
+ methods << "silence_redefinition_of_method def #{name}?; !!self.#{name}; end"
137
122
  end
138
123
  end
139
124
  end
125
+
126
+ location = caller_locations(1, 1).first
127
+ class_eval(["class << self", *class_methods, "end", *methods].join(";").tr("\n", ";"), location.path, location.lineno)
128
+
129
+ attrs.each { |name| public_send("#{name}=", default) }
140
130
  end
141
131
  end