activesupport 6.1.4.1 → 7.0.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (185) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +325 -395
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -2
  5. data/lib/active_support/actionable_error.rb +1 -1
  6. data/lib/active_support/array_inquirer.rb +0 -2
  7. data/lib/active_support/backtrace_cleaner.rb +2 -2
  8. data/lib/active_support/benchmarkable.rb +2 -2
  9. data/lib/active_support/cache/file_store.rb +15 -9
  10. data/lib/active_support/cache/mem_cache_store.rb +148 -37
  11. data/lib/active_support/cache/memory_store.rb +24 -16
  12. data/lib/active_support/cache/null_store.rb +10 -2
  13. data/lib/active_support/cache/redis_cache_store.rb +68 -85
  14. data/lib/active_support/cache/strategy/local_cache.rb +38 -61
  15. data/lib/active_support/cache.rb +299 -147
  16. data/lib/active_support/callbacks.rb +184 -85
  17. data/lib/active_support/code_generator.rb +65 -0
  18. data/lib/active_support/concern.rb +5 -5
  19. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +2 -4
  20. data/lib/active_support/concurrency/share_lock.rb +2 -2
  21. data/lib/active_support/configurable.rb +8 -5
  22. data/lib/active_support/configuration_file.rb +1 -1
  23. data/lib/active_support/core_ext/array/access.rb +1 -5
  24. data/lib/active_support/core_ext/array/conversions.rb +13 -12
  25. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  26. data/lib/active_support/core_ext/array/grouping.rb +6 -6
  27. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  28. data/lib/active_support/core_ext/array.rb +1 -0
  29. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  30. data/lib/active_support/core_ext/class/subclasses.rb +25 -17
  31. data/lib/active_support/core_ext/date/blank.rb +1 -1
  32. data/lib/active_support/core_ext/date/calculations.rb +24 -9
  33. data/lib/active_support/core_ext/date/conversions.rb +14 -14
  34. data/lib/active_support/core_ext/date/deprecated_conversions.rb +40 -0
  35. data/lib/active_support/core_ext/date.rb +1 -0
  36. data/lib/active_support/core_ext/date_and_time/calculations.rb +4 -4
  37. data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
  38. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  39. data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
  40. data/lib/active_support/core_ext/date_time/conversions.rb +13 -13
  41. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +36 -0
  42. data/lib/active_support/core_ext/date_time.rb +1 -0
  43. data/lib/active_support/core_ext/digest/uuid.rb +39 -13
  44. data/lib/active_support/core_ext/enumerable.rb +112 -38
  45. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  46. data/lib/active_support/core_ext/hash/conversions.rb +0 -1
  47. data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
  48. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  49. data/lib/active_support/core_ext/hash/keys.rb +4 -4
  50. data/lib/active_support/core_ext/integer/inflections.rb +12 -12
  51. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  52. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  53. data/lib/active_support/core_ext/module/attribute_accessors.rb +2 -0
  54. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +19 -10
  55. data/lib/active_support/core_ext/module/delegation.rb +2 -8
  56. data/lib/active_support/core_ext/name_error.rb +2 -8
  57. data/lib/active_support/core_ext/numeric/conversions.rb +80 -77
  58. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  59. data/lib/active_support/core_ext/numeric.rb +1 -0
  60. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  61. data/lib/active_support/core_ext/object/blank.rb +2 -2
  62. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  63. data/lib/active_support/core_ext/object/duplicable.rb +15 -4
  64. data/lib/active_support/core_ext/object/json.rb +30 -25
  65. data/lib/active_support/core_ext/object/to_query.rb +2 -4
  66. data/lib/active_support/core_ext/object/try.rb +20 -20
  67. data/lib/active_support/core_ext/object/with_options.rb +21 -2
  68. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  69. data/lib/active_support/core_ext/pathname.rb +3 -0
  70. data/lib/active_support/core_ext/range/compare_range.rb +0 -25
  71. data/lib/active_support/core_ext/range/conversions.rb +8 -8
  72. data/lib/active_support/core_ext/range/deprecated_conversions.rb +36 -0
  73. data/lib/active_support/core_ext/range/each.rb +1 -1
  74. data/lib/active_support/core_ext/range/include_time_with_zone.rb +3 -26
  75. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  76. data/lib/active_support/core_ext/range.rb +1 -1
  77. data/lib/active_support/core_ext/securerandom.rb +1 -1
  78. data/lib/active_support/core_ext/string/conversions.rb +2 -2
  79. data/lib/active_support/core_ext/string/filters.rb +1 -1
  80. data/lib/active_support/core_ext/string/inflections.rb +1 -5
  81. data/lib/active_support/core_ext/string/inquiry.rb +1 -1
  82. data/lib/active_support/core_ext/string/output_safety.rb +94 -38
  83. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
  84. data/lib/active_support/core_ext/time/calculations.rb +13 -8
  85. data/lib/active_support/core_ext/time/conversions.rb +13 -12
  86. data/lib/active_support/core_ext/time/deprecated_conversions.rb +73 -0
  87. data/lib/active_support/core_ext/time/zones.rb +10 -26
  88. data/lib/active_support/core_ext/time.rb +1 -0
  89. data/lib/active_support/core_ext/uri.rb +3 -27
  90. data/lib/active_support/core_ext.rb +1 -0
  91. data/lib/active_support/current_attributes.rb +31 -14
  92. data/lib/active_support/dependencies/interlock.rb +10 -18
  93. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  94. data/lib/active_support/dependencies.rb +58 -788
  95. data/lib/active_support/deprecation/behaviors.rb +8 -5
  96. data/lib/active_support/deprecation/disallowed.rb +3 -3
  97. data/lib/active_support/deprecation/method_wrappers.rb +3 -3
  98. data/lib/active_support/deprecation/proxy_wrappers.rb +2 -2
  99. data/lib/active_support/deprecation.rb +2 -2
  100. data/lib/active_support/descendants_tracker.rb +174 -68
  101. data/lib/active_support/digest.rb +5 -3
  102. data/lib/active_support/duration/iso8601_parser.rb +3 -3
  103. data/lib/active_support/duration/iso8601_serializer.rb +9 -1
  104. data/lib/active_support/duration.rb +81 -51
  105. data/lib/active_support/encrypted_configuration.rb +45 -3
  106. data/lib/active_support/encrypted_file.rb +21 -10
  107. data/lib/active_support/environment_inquirer.rb +1 -1
  108. data/lib/active_support/error_reporter.rb +117 -0
  109. data/lib/active_support/evented_file_update_checker.rb +20 -7
  110. data/lib/active_support/execution_context/test_helper.rb +13 -0
  111. data/lib/active_support/execution_context.rb +53 -0
  112. data/lib/active_support/execution_wrapper.rb +43 -21
  113. data/lib/active_support/executor/test_helper.rb +7 -0
  114. data/lib/active_support/fork_tracker.rb +19 -12
  115. data/lib/active_support/gem_version.rb +5 -5
  116. data/lib/active_support/hash_with_indifferent_access.rb +3 -1
  117. data/lib/active_support/html_safe_translation.rb +43 -0
  118. data/lib/active_support/i18n.rb +1 -0
  119. data/lib/active_support/i18n_railtie.rb +1 -1
  120. data/lib/active_support/inflector/inflections.rb +23 -7
  121. data/lib/active_support/inflector/methods.rb +29 -55
  122. data/lib/active_support/inflector/transliterate.rb +1 -1
  123. data/lib/active_support/isolated_execution_state.rb +72 -0
  124. data/lib/active_support/json/encoding.rb +3 -3
  125. data/lib/active_support/key_generator.rb +22 -5
  126. data/lib/active_support/lazy_load_hooks.rb +28 -4
  127. data/lib/active_support/locale/en.yml +1 -1
  128. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  129. data/lib/active_support/log_subscriber.rb +15 -5
  130. data/lib/active_support/logger_thread_safe_level.rb +4 -13
  131. data/lib/active_support/message_encryptor.rb +12 -6
  132. data/lib/active_support/message_verifier.rb +46 -14
  133. data/lib/active_support/messages/metadata.rb +2 -2
  134. data/lib/active_support/multibyte/chars.rb +10 -11
  135. data/lib/active_support/multibyte/unicode.rb +0 -12
  136. data/lib/active_support/multibyte.rb +1 -1
  137. data/lib/active_support/notifications/fanout.rb +91 -65
  138. data/lib/active_support/notifications/instrumenter.rb +32 -15
  139. data/lib/active_support/notifications.rb +23 -23
  140. data/lib/active_support/number_helper/number_converter.rb +1 -3
  141. data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
  142. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
  143. data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
  144. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -1
  145. data/lib/active_support/number_helper/rounding_helper.rb +1 -5
  146. data/lib/active_support/number_helper.rb +4 -5
  147. data/lib/active_support/option_merger.rb +10 -18
  148. data/lib/active_support/ordered_hash.rb +1 -1
  149. data/lib/active_support/ordered_options.rb +1 -1
  150. data/lib/active_support/parameter_filter.rb +20 -11
  151. data/lib/active_support/per_thread_registry.rb +5 -0
  152. data/lib/active_support/railtie.rb +69 -19
  153. data/lib/active_support/reloader.rb +1 -1
  154. data/lib/active_support/rescuable.rb +12 -12
  155. data/lib/active_support/ruby_features.rb +7 -0
  156. data/lib/active_support/secure_compare_rotator.rb +2 -2
  157. data/lib/active_support/string_inquirer.rb +0 -2
  158. data/lib/active_support/subscriber.rb +7 -18
  159. data/lib/active_support/tagged_logging.rb +2 -2
  160. data/lib/active_support/test_case.rb +13 -21
  161. data/lib/active_support/testing/assertions.rb +36 -6
  162. data/lib/active_support/testing/deprecation.rb +52 -1
  163. data/lib/active_support/testing/isolation.rb +30 -29
  164. data/lib/active_support/testing/method_call_assertions.rb +5 -5
  165. data/lib/active_support/testing/parallelization/server.rb +4 -0
  166. data/lib/active_support/testing/parallelization/worker.rb +3 -0
  167. data/lib/active_support/testing/parallelization.rb +4 -0
  168. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  169. data/lib/active_support/testing/stream.rb +3 -5
  170. data/lib/active_support/testing/tagged_logging.rb +1 -1
  171. data/lib/active_support/testing/time_helpers.rb +13 -2
  172. data/lib/active_support/time_with_zone.rb +43 -22
  173. data/lib/active_support/values/time_zone.rb +35 -14
  174. data/lib/active_support/version.rb +1 -1
  175. data/lib/active_support/xml_mini/jdom.rb +1 -1
  176. data/lib/active_support/xml_mini/libxml.rb +5 -5
  177. data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
  178. data/lib/active_support/xml_mini/nokogiri.rb +4 -4
  179. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  180. data/lib/active_support/xml_mini/rexml.rb +1 -1
  181. data/lib/active_support/xml_mini.rb +5 -4
  182. data/lib/active_support.rb +17 -1
  183. metadata +26 -23
  184. data/lib/active_support/core_ext/marshal.rb +0 -26
  185. data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
@@ -1,8 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ module ActiveSupport
4
+ module EnumerableCoreExt # :nodoc:
5
+ module Constants
6
+ private
7
+ def const_missing(name)
8
+ if name == :SoleItemExpectedError
9
+ ::ActiveSupport::EnumerableCoreExt::SoleItemExpectedError
10
+ else
11
+ super
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+
3
18
  module Enumerable
4
- INDEX_WITH_DEFAULT = Object.new
5
- private_constant :INDEX_WITH_DEFAULT
19
+ # Error generated by +sole+ when called on an enumerable that doesn't have
20
+ # exactly one item.
21
+ class SoleItemExpectedError < StandardError; end
22
+
23
+ # HACK: For performance reasons, Enumerable shouldn't have any constants of its own.
24
+ # So we move SoleItemExpectedError into ActiveSupport::EnumerableCoreExt.
25
+ ActiveSupport::EnumerableCoreExt::SoleItemExpectedError = remove_const(:SoleItemExpectedError)
26
+ singleton_class.prepend(ActiveSupport::EnumerableCoreExt::Constants)
6
27
 
7
28
  # Enumerable#sum was added in Ruby 2.4, but it only works with Numeric elements
8
29
  # when we omit an identity.
@@ -16,31 +37,63 @@ module Enumerable
16
37
 
17
38
  # :startdoc:
18
39
 
40
+ # Calculates the minimum from the extracted elements.
41
+ #
42
+ # payments = [Payment.new(5), Payment.new(15), Payment.new(10)]
43
+ # payments.minimum(:price) # => 5
44
+ def minimum(key)
45
+ map(&key).min
46
+ end
47
+
48
+ # Calculates the maximum from the extracted elements.
49
+ #
50
+ # payments = [Payment.new(5), Payment.new(15), Payment.new(10)]
51
+ # payments.maximum(:price) # => 15
52
+ def maximum(key)
53
+ map(&key).max
54
+ end
55
+
19
56
  # Calculates a sum from the elements.
20
57
  #
21
- # payments.sum { |p| p.price * p.tax_rate }
22
- # payments.sum(&:price)
58
+ # payments.sum { |p| p.price * p.tax_rate }
59
+ # payments.sum(&:price)
23
60
  #
24
61
  # The latter is a shortcut for:
25
62
  #
26
- # payments.inject(0) { |sum, p| sum + p.price }
63
+ # payments.inject(0) { |sum, p| sum + p.price }
27
64
  #
28
65
  # It can also calculate the sum without the use of a block.
29
66
  #
30
- # [5, 15, 10].sum # => 30
31
- # ['foo', 'bar'].sum # => "foobar"
32
- # [[1, 2], [3, 1, 5]].sum # => [1, 2, 3, 1, 5]
67
+ # [5, 15, 10].sum # => 30
68
+ # ['foo', 'bar'].sum('') # => "foobar"
69
+ # [[1, 2], [3, 1, 5]].sum([]) # => [1, 2, 3, 1, 5]
33
70
  #
34
71
  # The default sum of an empty list is zero. You can override this default:
35
72
  #
36
- # [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
73
+ # [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
37
74
  def sum(identity = nil, &block)
38
75
  if identity
39
76
  _original_sum_with_required_identity(identity, &block)
40
77
  elsif block_given?
41
- map(&block).sum(identity)
78
+ map(&block).sum
42
79
  else
43
- inject(:+) || 0
80
+ first = true
81
+
82
+ reduce(nil) do |sum, value|
83
+ if first
84
+ first = false
85
+
86
+ unless value.is_a?(Numeric) || value.respond_to?(:coerce)
87
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
88
+ Rails 7.0 has deprecated Enumerable.sum in favor of Ruby's native implementation available since 2.4.
89
+ Sum of non-numeric elements requires an initial argument.
90
+ MSG
91
+ end
92
+ value
93
+ else
94
+ sum + value
95
+ end
96
+ end || 0
44
97
  end
45
98
  end
46
99
 
@@ -75,17 +128,17 @@ module Enumerable
75
128
  #
76
129
  # %i( created_at updated_at ).index_with(Time.now)
77
130
  # # => { created_at: 2020-03-09 22:31:47, updated_at: 2020-03-09 22:31:47 }
78
- def index_with(default = INDEX_WITH_DEFAULT)
131
+ def index_with(default = (no_default = true))
79
132
  if block_given?
80
133
  result = {}
81
134
  each { |elem| result[elem] = yield(elem) }
82
135
  result
83
- elsif default != INDEX_WITH_DEFAULT
136
+ elsif no_default
137
+ to_enum(:index_with) { size if respond_to?(:size) }
138
+ else
84
139
  result = {}
85
140
  each { |elem| result[elem] = default }
86
141
  result
87
- else
88
- to_enum(:index_with) { size if respond_to?(:size) }
89
142
  end
90
143
  end
91
144
 
@@ -96,8 +149,8 @@ module Enumerable
96
149
  def many?
97
150
  cnt = 0
98
151
  if block_given?
99
- any? do |element|
100
- cnt += 1 if yield element
152
+ any? do |*args|
153
+ cnt += 1 if yield(*args)
101
154
  cnt > 1
102
155
  end
103
156
  else
@@ -136,11 +189,7 @@ module Enumerable
136
189
  elements.flatten!(1)
137
190
  reject { |element| elements.include?(element) }
138
191
  end
139
-
140
- # Alias for #excluding.
141
- def without(*elements)
142
- excluding(*elements)
143
- end
192
+ alias :without :excluding
144
193
 
145
194
  # Extract the given key from each element in the enumerable.
146
195
  #
@@ -178,40 +227,66 @@ module Enumerable
178
227
  # Returns a new +Array+ without the blank items.
179
228
  # Uses Object#blank? for determining if an item is blank.
180
229
  #
181
- # [1, "", nil, 2, " ", [], {}, false, true].compact_blank
182
- # # => [1, 2, true]
230
+ # [1, "", nil, 2, " ", [], {}, false, true].compact_blank
231
+ # # => [1, 2, true]
183
232
  #
184
- # Set.new([nil, "", 1, 2])
185
- # # => [2, 1] (or [1, 2])
233
+ # Set.new([nil, "", 1, false]).compact_blank
234
+ # # => [1]
186
235
  #
187
236
  # When called on a +Hash+, returns a new +Hash+ without the blank values.
188
237
  #
189
- # { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank
190
- # #=> { b: 1, f: true }
238
+ # { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank
239
+ # # => { b: 1, f: true }
191
240
  def compact_blank
192
241
  reject(&:blank?)
193
242
  end
243
+
244
+ # Returns a new +Array+ where the order has been set to that provided in the +series+, based on the +key+ of the
245
+ # objects in the original enumerable.
246
+ #
247
+ # [ Person.find(5), Person.find(3), Person.find(1) ].in_order_of(:id, [ 1, 5, 3 ])
248
+ # # => [ Person.find(1), Person.find(5), Person.find(3) ]
249
+ #
250
+ # If the +series+ include keys that have no corresponding element in the Enumerable, these are ignored.
251
+ # If the Enumerable has additional elements that aren't named in the +series+, these are not included in the result.
252
+ def in_order_of(key, series)
253
+ group_by(&key).values_at(*series).flatten(1).compact
254
+ end
255
+
256
+ # Returns the sole item in the enumerable. If there are no items, or more
257
+ # than one item, raises +Enumerable::SoleItemExpectedError+.
258
+ #
259
+ # ["x"].sole # => "x"
260
+ # Set.new.sole # => Enumerable::SoleItemExpectedError: no item found
261
+ # { a: 1, b: 2 }.sole # => Enumerable::SoleItemExpectedError: multiple items found
262
+ def sole
263
+ case count
264
+ when 1 then return first # rubocop:disable Style/RedundantReturn
265
+ when 0 then raise ActiveSupport::EnumerableCoreExt::SoleItemExpectedError, "no item found"
266
+ when 2.. then raise ActiveSupport::EnumerableCoreExt::SoleItemExpectedError, "multiple items found"
267
+ end
268
+ end
194
269
  end
195
270
 
196
271
  class Hash
197
272
  # Hash#reject has its own definition, so this needs one too.
198
- def compact_blank #:nodoc:
273
+ def compact_blank # :nodoc:
199
274
  reject { |_k, v| v.blank? }
200
275
  end
201
276
 
202
277
  # Removes all blank values from the +Hash+ in place and returns self.
203
278
  # Uses Object#blank? for determining if a value is blank.
204
279
  #
205
- # h = { a: "", b: 1, c: nil, d: [], e: false, f: true }
206
- # h.compact_blank!
207
- # # => { b: 1, f: true }
280
+ # h = { a: "", b: 1, c: nil, d: [], e: false, f: true }
281
+ # h.compact_blank!
282
+ # # => { b: 1, f: true }
208
283
  def compact_blank!
209
284
  # use delete_if rather than reject! because it always returns self even if nothing changed
210
285
  delete_if { |_k, v| v.blank? }
211
286
  end
212
287
  end
213
288
 
214
- class Range #:nodoc:
289
+ class Range # :nodoc:
215
290
  # Optimize range sum to use arithmetic progression if a block is not given and
216
291
  # we have a range of numeric values.
217
292
  def sum(identity = nil)
@@ -236,8 +311,7 @@ using Module.new {
236
311
  end
237
312
  }
238
313
 
239
- class Array #:nodoc:
240
- # Array#sum was added in Ruby 2.4 but it only works with Numeric elements.
314
+ class Array # :nodoc:
241
315
  def sum(init = nil, &block)
242
316
  if init.is_a?(Numeric) || first.is_a?(Numeric)
243
317
  init ||= 0
@@ -250,9 +324,9 @@ class Array #:nodoc:
250
324
  # Removes all blank elements from the +Array+ in place and returns self.
251
325
  # Uses Object#blank? for determining if an item is blank.
252
326
  #
253
- # a = [1, "", nil, 2, " ", [], {}, false, true]
254
- # a.compact_blank!
255
- # # => [1, 2, true]
327
+ # a = [1, "", nil, 2, " ", [], {}, false, true]
328
+ # a.compact_blank!
329
+ # # => [1, 2, true]
256
330
  def compact_blank!
257
331
  # use delete_if rather than reject! because it always returns self even if nothing changed
258
332
  delete_if(&:blank?)
@@ -53,7 +53,7 @@ class File
53
53
  end
54
54
 
55
55
  # Private utility method.
56
- def self.probe_stat_in(dir) #:nodoc:
56
+ def self.probe_stat_in(dir) # :nodoc:
57
57
  basename = [
58
58
  ".permissions_check",
59
59
  Thread.current.object_id,
@@ -64,6 +64,8 @@ class File
64
64
  file_name = join(dir, basename)
65
65
  FileUtils.touch(file_name)
66
66
  stat(file_name)
67
+ rescue Errno::ENOENT
68
+ file_name = nil
67
69
  ensure
68
70
  FileUtils.rm_f(file_name) if file_name
69
71
  end
@@ -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/object/blank"
5
4
  require "active_support/core_ext/object/to_param"
6
5
  require "active_support/core_ext/object/to_query"
@@ -5,10 +5,10 @@ class Hash
5
5
  # This includes the values from the root hash and from all
6
6
  # nested hashes and arrays.
7
7
  #
8
- # hash = { person: { name: 'Rob', age: '28' } }
8
+ # hash = { person: { name: 'Rob', age: '28' } }
9
9
  #
10
- # hash.deep_transform_values{ |value| value.to_s.upcase }
11
- # # => {person: {name: "ROB", age: "28"}}
10
+ # hash.deep_transform_values{ |value| value.to_s.upcase }
11
+ # # => {person: {name: "ROB", age: "28"}}
12
12
  def deep_transform_values(&block)
13
13
  _deep_transform_values_in_object(self, &block)
14
14
  end
@@ -3,7 +3,7 @@
3
3
  require "active_support/hash_with_indifferent_access"
4
4
 
5
5
  class Hash
6
- # Returns an <tt>ActiveSupport::HashWithIndifferentAccess</tt> out of its receiver:
6
+ # Returns an ActiveSupport::HashWithIndifferentAccess out of its receiver:
7
7
  #
8
8
  # { a: 1 }.with_indifferent_access['a'] # => 1
9
9
  def with_indifferent_access
@@ -13,8 +13,8 @@ class Hash
13
13
  # Called when object is nested under an object that receives
14
14
  # #with_indifferent_access. This method will be called on the current object
15
15
  # by the enclosing object and is aliased to #with_indifferent_access by
16
- # default. Subclasses of Hash may overwrite this method to return +self+ if
17
- # converting to an <tt>ActiveSupport::HashWithIndifferentAccess</tt> would not be
16
+ # default. Subclasses of Hash may override this method to return +self+ if
17
+ # converting to an ActiveSupport::HashWithIndifferentAccess would not be
18
18
  # desirable.
19
19
  #
20
20
  # b = { b: 1 }
@@ -58,10 +58,10 @@ class Hash
58
58
  # This includes the keys from the root hash and from all
59
59
  # nested hashes and arrays.
60
60
  #
61
- # hash = { person: { name: 'Rob', age: '28' } }
61
+ # hash = { person: { name: 'Rob', age: '28' } }
62
62
  #
63
- # hash.deep_transform_keys{ |key| key.to_s.upcase }
64
- # # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
63
+ # hash.deep_transform_keys{ |key| key.to_s.upcase }
64
+ # # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
65
65
  def deep_transform_keys(&block)
66
66
  _deep_transform_keys_in_object(self, &block)
67
67
  end
@@ -116,7 +116,7 @@ class Hash
116
116
  def _deep_transform_keys_in_object(object, &block)
117
117
  case object
118
118
  when Hash
119
- object.each_with_object({}) do |(key, value), result|
119
+ object.each_with_object(self.class.new) do |(key, value), result|
120
120
  result[yield(key)] = _deep_transform_keys_in_object(value, &block)
121
121
  end
122
122
  when Array
@@ -6,12 +6,12 @@ class Integer
6
6
  # Ordinalize turns a number into an ordinal string used to denote the
7
7
  # position in an ordered sequence such as 1st, 2nd, 3rd, 4th.
8
8
  #
9
- # 1.ordinalize # => "1st"
10
- # 2.ordinalize # => "2nd"
11
- # 1002.ordinalize # => "1002nd"
12
- # 1003.ordinalize # => "1003rd"
13
- # -11.ordinalize # => "-11th"
14
- # -1001.ordinalize # => "-1001st"
9
+ # 1.ordinalize # => "1st"
10
+ # 2.ordinalize # => "2nd"
11
+ # 1002.ordinalize # => "1002nd"
12
+ # 1003.ordinalize # => "1003rd"
13
+ # -11.ordinalize # => "-11th"
14
+ # -1001.ordinalize # => "-1001st"
15
15
  def ordinalize
16
16
  ActiveSupport::Inflector.ordinalize(self)
17
17
  end
@@ -19,12 +19,12 @@ class Integer
19
19
  # Ordinal returns the suffix used to denote the position
20
20
  # in an ordered sequence such as 1st, 2nd, 3rd, 4th.
21
21
  #
22
- # 1.ordinal # => "st"
23
- # 2.ordinal # => "nd"
24
- # 1002.ordinal # => "nd"
25
- # 1003.ordinal # => "rd"
26
- # -11.ordinal # => "th"
27
- # -1001.ordinal # => "st"
22
+ # 1.ordinal # => "st"
23
+ # 2.ordinal # => "nd"
24
+ # 1002.ordinal # => "nd"
25
+ # 1003.ordinal # => "rd"
26
+ # -11.ordinal # => "th"
27
+ # -1001.ordinal # => "st"
28
28
  def ordinal
29
29
  ActiveSupport::Inflector.ordinal(self)
30
30
  end
@@ -11,14 +11,14 @@ module Kernel
11
11
  # end
12
12
  #
13
13
  # noisy_call # warning voiced
14
- def silence_warnings
15
- with_warnings(nil) { yield }
14
+ def silence_warnings(&block)
15
+ with_warnings(nil, &block)
16
16
  end
17
17
 
18
18
  # Sets $VERBOSE to +true+ for the duration of the block and back to its
19
19
  # original value afterwards.
20
- def enable_warnings
21
- with_warnings(true) { yield }
20
+ def enable_warnings(&block)
21
+ with_warnings(true, &block)
22
22
  end
23
23
 
24
24
  # Sets $VERBOSE for the duration of the block and back to its original
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kernel
4
- # class_eval on an object acts like singleton_class.class_eval.
4
+ # class_eval on an object acts like +singleton_class.class_eval+.
5
5
  def class_eval(*args, &block)
6
6
  singleton_class.class_eval(*args, &block)
7
7
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # == Attribute Accessors
4
+ #
3
5
  # Extends the module object with class/module and instance accessors for
4
6
  # class/module attributes, just like the native attr* accessors for instance
5
7
  # attributes.
@@ -1,11 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # == Attribute Accessors per Thread
4
+ #
3
5
  # Extends the module object with class/module and instance accessors for
4
6
  # class/module attributes, just like the native attr* accessors for instance
5
7
  # attributes, but does so on a per-thread basis.
6
8
  #
7
9
  # So the values are scoped within the Thread.current space under the class name
8
10
  # of the module.
11
+ #
12
+ # Note that it can also be scoped per-fiber if +Rails.application.config.active_support.isolation_level+
13
+ # is set to +:fiber+.
9
14
  class Module
10
15
  # Defines a per-thread class attribute and creates class and instance reader methods.
11
16
  # The underlying per-thread class variable is set to +nil+, if it is not previously defined.
@@ -14,9 +19,9 @@ class Module
14
19
  # thread_mattr_reader :user
15
20
  # end
16
21
  #
17
- # Current.user # => nil
18
- # Thread.current[:attr_Current_user] = "DHH"
22
+ # Current.user = "DHH"
19
23
  # Current.user # => "DHH"
24
+ # Thread.new { Current.user }.value # => nil
20
25
  #
21
26
  # The attribute name must be a valid method name in Ruby.
22
27
  #
@@ -41,7 +46,8 @@ class Module
41
46
  # to work with inheritance via polymorphism.
42
47
  class_eval(<<-EOS, __FILE__, __LINE__ + 1)
43
48
  def self.#{sym}
44
- Thread.current["attr_" + name + "_#{sym}"]
49
+ @__thread_mattr_#{sym} ||= "attr_\#{name}_#{sym}"
50
+ ::ActiveSupport::IsolatedExecutionState[@__thread_mattr_#{sym}]
45
51
  end
46
52
  EOS
47
53
 
@@ -53,7 +59,7 @@ class Module
53
59
  EOS
54
60
  end
55
61
 
56
- Thread.current["attr_" + name + "_#{sym}"] = default unless default.nil?
62
+ ::ActiveSupport::IsolatedExecutionState["attr_#{name}_#{sym}"] = default unless default.nil?
57
63
  end
58
64
  end
59
65
  alias :thread_cattr_reader :thread_mattr_reader
@@ -84,7 +90,8 @@ class Module
84
90
  # to work with inheritance via polymorphism.
85
91
  class_eval(<<-EOS, __FILE__, __LINE__ + 1)
86
92
  def self.#{sym}=(obj)
87
- Thread.current["attr_" + name + "_#{sym}"] = obj
93
+ @__thread_mattr_#{sym} ||= "attr_\#{name}_#{sym}"
94
+ ::ActiveSupport::IsolatedExecutionState[@__thread_mattr_#{sym}] = obj
88
95
  end
89
96
  EOS
90
97
 
@@ -111,16 +118,18 @@ class Module
111
118
  # Account.user # => "DHH"
112
119
  # Account.new.user # => "DHH"
113
120
  #
121
+ # Unlike +mattr_accessor+, values are *not* shared with subclasses or parent classes.
114
122
  # If a subclass changes the value, the parent class' value is not changed.
115
- # Similarly, if the parent class changes the value, the value of subclasses
116
- # is not changed.
123
+ # If the parent class changes the value, the value of subclasses is not changed.
117
124
  #
118
125
  # class Customer < Account
119
126
  # end
120
127
  #
121
- # Customer.user = "Rafael"
122
- # Customer.user # => "Rafael"
123
- # Account.user # => "DHH"
128
+ # Account.user # => "DHH"
129
+ # Customer.user # => nil
130
+ # Customer.user = "Rafael"
131
+ # Customer.user # => "Rafael"
132
+ # Account.user # => "DHH"
124
133
  #
125
134
  # To omit the instance writer method, pass <tt>instance_writer: false</tt>.
126
135
  # To omit the instance reader method, pass <tt>instance_reader: false</tt>.
@@ -199,13 +199,7 @@ class Module
199
199
 
200
200
  # Attribute writer methods only accept one argument. Makes sure []=
201
201
  # methods still accept two arguments.
202
- definition = if /[^\]]=$/.match?(method)
203
- "arg"
204
- elsif RUBY_VERSION >= "2.7"
205
- "..."
206
- else
207
- "*args, &block"
208
- end
202
+ definition = /[^\]]=\z/.match?(method) ? "arg" : "..."
209
203
 
210
204
  # The following generated method calls the target exactly once, storing
211
205
  # the returned value in a dummy variable.
@@ -324,7 +318,7 @@ class Module
324
318
  end
325
319
  end
326
320
  end
327
- ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
321
+ ruby2_keywords(:method_missing)
328
322
  RUBY
329
323
  end
330
324
  end
@@ -53,13 +53,7 @@ class NameError
53
53
  UNBOUND_METHOD_MODULE_NAME = Module.instance_method(:name)
54
54
  private_constant :UNBOUND_METHOD_MODULE_NAME
55
55
 
56
- if UnboundMethod.method_defined?(:bind_call)
57
- def real_mod_name(mod)
58
- UNBOUND_METHOD_MODULE_NAME.bind_call(mod)
59
- end
60
- else
61
- def real_mod_name(mod)
62
- UNBOUND_METHOD_MODULE_NAME.bind(mod).call
63
- end
56
+ def real_mod_name(mod)
57
+ UNBOUND_METHOD_MODULE_NAME.bind_call(mod)
64
58
  end
65
59
  end