activesupport 6.0.6.1 → 7.1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/string/filters"
4
3
  require "active_support/inflector"
5
4
 
6
5
  class Module
@@ -11,20 +10,12 @@ class Module
11
10
  if defined?(@parent_name)
12
11
  @parent_name
13
12
  else
14
- parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
13
+ parent_name = name =~ /::[^:]+\z/ ? -$` : nil
15
14
  @parent_name = parent_name unless frozen?
16
15
  parent_name
17
16
  end
18
17
  end
19
18
 
20
- def parent_name
21
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
22
- `Module#parent_name` has been renamed to `module_parent_name`.
23
- `parent_name` is deprecated and will be removed in Rails 6.1.
24
- MSG
25
- module_parent_name
26
- end
27
-
28
19
  # Returns the module which contains this one according to its name.
29
20
  #
30
21
  # module M
@@ -44,14 +35,6 @@ class Module
44
35
  module_parent_name ? ActiveSupport::Inflector.constantize(module_parent_name) : Object
45
36
  end
46
37
 
47
- def parent
48
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
49
- `Module#parent` has been renamed to `module_parent`.
50
- `parent` is deprecated and will be removed in Rails 6.1.
51
- MSG
52
- module_parent
53
- end
54
-
55
38
  # Returns all the parents of this module according to its name, ordered from
56
39
  # nested outwards. The receiver is not contained within the result.
57
40
  #
@@ -76,12 +59,4 @@ class Module
76
59
  parents << Object unless parents.include? Object
77
60
  parents
78
61
  end
79
-
80
- def parents
81
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
82
- `Module#parents` has been renamed to `module_parents`.
83
- `parents` is deprecated and will be removed in Rails 6.1.
84
- MSG
85
- module_parents
86
- end
87
62
  end
@@ -14,9 +14,22 @@ class NameError
14
14
  # It extends NameError#message with spell corrections which are SLOW.
15
15
  # We should use original_message message instead.
16
16
  message = respond_to?(:original_message) ? original_message : self.message
17
+ return unless message.start_with?("uninitialized constant ")
17
18
 
18
- if /undefined local variable or method/ !~ message
19
- $1 if /((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/ =~ message
19
+ receiver = begin
20
+ self.receiver
21
+ rescue ArgumentError
22
+ nil
23
+ end
24
+
25
+ if receiver == Object
26
+ name.to_s
27
+ elsif receiver
28
+ "#{real_mod_name(receiver)}::#{self.name}"
29
+ else
30
+ if match = message.match(/((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/)
31
+ match[1]
32
+ end
20
33
  end
21
34
  end
22
35
 
@@ -35,4 +48,12 @@ class NameError
35
48
  missing_name == name.to_s
36
49
  end
37
50
  end
51
+
52
+ private
53
+ UNBOUND_METHOD_MODULE_NAME = Module.instance_method(:name)
54
+ private_constant :UNBOUND_METHOD_MODULE_NAME
55
+
56
+ def real_mod_name(mod)
57
+ UNBOUND_METHOD_MODULE_NAME.bind_call(mod)
58
+ end
38
59
  end
@@ -7,6 +7,7 @@ class Numeric
7
7
  TERABYTE = GIGABYTE * 1024
8
8
  PETABYTE = TERABYTE * 1024
9
9
  EXABYTE = PETABYTE * 1024
10
+ ZETTABYTE = EXABYTE * 1024
10
11
 
11
12
  # Enables the use of byte calculations and declarations, like 45.bytes + 2.6.megabytes
12
13
  #
@@ -63,4 +64,12 @@ class Numeric
63
64
  self * EXABYTE
64
65
  end
65
66
  alias :exabyte :exabytes
67
+
68
+ # Returns the number of bytes equivalent to the zettabytes provided.
69
+ #
70
+ # 2.zettabytes # => 2_361_183_241_434_822_606_848
71
+ def zettabytes
72
+ self * ZETTABYTE
73
+ end
74
+ alias :zettabyte :zettabytes
66
75
  end
@@ -2,13 +2,16 @@
2
2
 
3
3
  require "active_support/core_ext/big_decimal/conversions"
4
4
  require "active_support/number_helper"
5
- require "active_support/core_ext/module/deprecation"
6
5
 
7
6
  module ActiveSupport
8
7
  module NumericWithFormat
8
+ # \Numeric With Format
9
+ #
9
10
  # Provides options for converting numbers into formatted strings.
10
11
  # Options are provided for phone numbers, currency, percentage,
11
- # precision, positional notation, file size and pretty printing.
12
+ # precision, positional notation, file size, and pretty printing.
13
+ #
14
+ # This method is aliased to <tt>to_formatted_s</tt>.
12
15
  #
13
16
  # ==== Options
14
17
  #
@@ -17,97 +20,102 @@ module ActiveSupport
17
20
  # ==== Examples
18
21
  #
19
22
  # Phone Numbers:
20
- # 5551234.to_s(:phone) # => "555-1234"
21
- # 1235551234.to_s(:phone) # => "123-555-1234"
22
- # 1235551234.to_s(:phone, area_code: true) # => "(123) 555-1234"
23
- # 1235551234.to_s(:phone, delimiter: ' ') # => "123 555 1234"
24
- # 1235551234.to_s(:phone, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
25
- # 1235551234.to_s(:phone, country_code: 1) # => "+1-123-555-1234"
26
- # 1235551234.to_s(:phone, country_code: 1, extension: 1343, delimiter: '.')
23
+ # 5551234.to_fs(:phone) # => "555-1234"
24
+ # 1235551234.to_fs(:phone) # => "123-555-1234"
25
+ # 1235551234.to_fs(:phone, area_code: true) # => "(123) 555-1234"
26
+ # 1235551234.to_fs(:phone, delimiter: ' ') # => "123 555 1234"
27
+ # 1235551234.to_fs(:phone, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
28
+ # 1235551234.to_fs(:phone, country_code: 1) # => "+1-123-555-1234"
29
+ # 1235551234.to_fs(:phone, country_code: 1, extension: 1343, delimiter: '.')
27
30
  # # => "+1.123.555.1234 x 1343"
28
31
  #
29
32
  # Currency:
30
- # 1234567890.50.to_s(:currency) # => "$1,234,567,890.50"
31
- # 1234567890.506.to_s(:currency) # => "$1,234,567,890.51"
32
- # 1234567890.506.to_s(:currency, precision: 3) # => "$1,234,567,890.506"
33
- # 1234567890.506.to_s(:currency, locale: :fr) # => "1 234 567 890,51 €"
34
- # -1234567890.50.to_s(:currency, negative_format: '(%u%n)')
33
+ # 1234567890.50.to_fs(:currency) # => "$1,234,567,890.50"
34
+ # 1234567890.506.to_fs(:currency) # => "$1,234,567,890.51"
35
+ # 1234567890.506.to_fs(:currency, precision: 3) # => "$1,234,567,890.506"
36
+ # 1234567890.506.to_fs(:currency, round_mode: :down) # => "$1,234,567,890.50"
37
+ # 1234567890.506.to_fs(:currency, locale: :fr) # => "1 234 567 890,51 €"
38
+ # -1234567890.50.to_fs(:currency, negative_format: '(%u%n)')
35
39
  # # => "($1,234,567,890.50)"
36
- # 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '')
40
+ # 1234567890.50.to_fs(:currency, unit: '&pound;', separator: ',', delimiter: '')
37
41
  # # => "&pound;1234567890,50"
38
- # 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
42
+ # 1234567890.50.to_fs(:currency, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
39
43
  # # => "1234567890,50 &pound;"
40
44
  #
41
45
  # Percentage:
42
- # 100.to_s(:percentage) # => "100.000%"
43
- # 100.to_s(:percentage, precision: 0) # => "100%"
44
- # 1000.to_s(:percentage, delimiter: '.', separator: ',') # => "1.000,000%"
45
- # 302.24398923423.to_s(:percentage, precision: 5) # => "302.24399%"
46
- # 1000.to_s(:percentage, locale: :fr) # => "1 000,000%"
47
- # 100.to_s(:percentage, format: '%n %') # => "100.000 %"
46
+ # 100.to_fs(:percentage) # => "100.000%"
47
+ # 100.to_fs(:percentage, precision: 0) # => "100%"
48
+ # 1000.to_fs(:percentage, delimiter: '.', separator: ',') # => "1.000,000%"
49
+ # 302.24398923423.to_fs(:percentage, precision: 5) # => "302.24399%"
50
+ # 302.24398923423.to_fs(:percentage, round_mode: :down) # => "302.243%"
51
+ # 1000.to_fs(:percentage, locale: :fr) # => "1 000,000%"
52
+ # 100.to_fs(:percentage, format: '%n %') # => "100.000 %"
48
53
  #
49
54
  # Delimited:
50
- # 12345678.to_s(:delimited) # => "12,345,678"
51
- # 12345678.05.to_s(:delimited) # => "12,345,678.05"
52
- # 12345678.to_s(:delimited, delimiter: '.') # => "12.345.678"
53
- # 12345678.to_s(:delimited, delimiter: ',') # => "12,345,678"
54
- # 12345678.05.to_s(:delimited, separator: ' ') # => "12,345,678 05"
55
- # 12345678.05.to_s(:delimited, locale: :fr) # => "12 345 678,05"
56
- # 98765432.98.to_s(:delimited, delimiter: ' ', separator: ',')
55
+ # 12345678.to_fs(:delimited) # => "12,345,678"
56
+ # 12345678.05.to_fs(:delimited) # => "12,345,678.05"
57
+ # 12345678.to_fs(:delimited, delimiter: '.') # => "12.345.678"
58
+ # 12345678.to_fs(:delimited, delimiter: ',') # => "12,345,678"
59
+ # 12345678.05.to_fs(:delimited, separator: ' ') # => "12,345,678 05"
60
+ # 12345678.05.to_fs(:delimited, locale: :fr) # => "12 345 678,05"
61
+ # 98765432.98.to_fs(:delimited, delimiter: ' ', separator: ',')
57
62
  # # => "98 765 432,98"
58
63
  #
59
64
  # Rounded:
60
- # 111.2345.to_s(:rounded) # => "111.235"
61
- # 111.2345.to_s(:rounded, precision: 2) # => "111.23"
62
- # 13.to_s(:rounded, precision: 5) # => "13.00000"
63
- # 389.32314.to_s(:rounded, precision: 0) # => "389"
64
- # 111.2345.to_s(:rounded, significant: true) # => "111"
65
- # 111.2345.to_s(:rounded, precision: 1, significant: true) # => "100"
66
- # 13.to_s(:rounded, precision: 5, significant: true) # => "13.000"
67
- # 111.234.to_s(:rounded, locale: :fr) # => "111,234"
68
- # 13.to_s(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true)
65
+ # 111.2345.to_fs(:rounded) # => "111.235"
66
+ # 111.2345.to_fs(:rounded, precision: 2) # => "111.23"
67
+ # 111.2345.to_fs(:rounded, precision: 2, round_mode: :up) # => "111.24"
68
+ # 13.to_fs(:rounded, precision: 5) # => "13.00000"
69
+ # 389.32314.to_fs(:rounded, precision: 0) # => "389"
70
+ # 111.2345.to_fs(:rounded, significant: true) # => "111"
71
+ # 111.2345.to_fs(:rounded, precision: 1, significant: true) # => "100"
72
+ # 13.to_fs(:rounded, precision: 5, significant: true) # => "13.000"
73
+ # 111.234.to_fs(:rounded, locale: :fr) # => "111,234"
74
+ # 13.to_fs(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true)
69
75
  # # => "13"
70
- # 389.32314.to_s(:rounded, precision: 4, significant: true) # => "389.3"
71
- # 1111.2345.to_s(:rounded, precision: 2, separator: ',', delimiter: '.')
76
+ # 389.32314.to_fs(:rounded, precision: 4, significant: true) # => "389.3"
77
+ # 1111.2345.to_fs(:rounded, precision: 2, separator: ',', delimiter: '.')
72
78
  # # => "1.111,23"
73
79
  #
74
80
  # Human-friendly size in Bytes:
75
- # 123.to_s(:human_size) # => "123 Bytes"
76
- # 1234.to_s(:human_size) # => "1.21 KB"
77
- # 12345.to_s(:human_size) # => "12.1 KB"
78
- # 1234567.to_s(:human_size) # => "1.18 MB"
79
- # 1234567890.to_s(:human_size) # => "1.15 GB"
80
- # 1234567890123.to_s(:human_size) # => "1.12 TB"
81
- # 1234567890123456.to_s(:human_size) # => "1.1 PB"
82
- # 1234567890123456789.to_s(:human_size) # => "1.07 EB"
83
- # 1234567.to_s(:human_size, precision: 2) # => "1.2 MB"
84
- # 483989.to_s(:human_size, precision: 2) # => "470 KB"
85
- # 1234567.to_s(:human_size, precision: 2, separator: ',') # => "1,2 MB"
86
- # 1234567890123.to_s(:human_size, precision: 5) # => "1.1228 TB"
87
- # 524288000.to_s(:human_size, precision: 5) # => "500 MB"
81
+ # 123.to_fs(:human_size) # => "123 Bytes"
82
+ # 1234.to_fs(:human_size) # => "1.21 KB"
83
+ # 12345.to_fs(:human_size) # => "12.1 KB"
84
+ # 1234567.to_fs(:human_size) # => "1.18 MB"
85
+ # 1234567890.to_fs(:human_size) # => "1.15 GB"
86
+ # 1234567890123.to_fs(:human_size) # => "1.12 TB"
87
+ # 1234567890123456.to_fs(:human_size) # => "1.1 PB"
88
+ # 1234567890123456789.to_fs(:human_size) # => "1.07 EB"
89
+ # 1234567.to_fs(:human_size, precision: 2) # => "1.2 MB"
90
+ # 1234567.to_fs(:human_size, precision: 2, round_mode: :up) # => "1.3 MB"
91
+ # 483989.to_fs(:human_size, precision: 2) # => "470 KB"
92
+ # 1234567.to_fs(:human_size, precision: 2, separator: ',') # => "1,2 MB"
93
+ # 1234567890123.to_fs(:human_size, precision: 5) # => "1.1228 TB"
94
+ # 524288000.to_fs(:human_size, precision: 5) # => "500 MB"
88
95
  #
89
96
  # Human-friendly format:
90
- # 123.to_s(:human) # => "123"
91
- # 1234.to_s(:human) # => "1.23 Thousand"
92
- # 12345.to_s(:human) # => "12.3 Thousand"
93
- # 1234567.to_s(:human) # => "1.23 Million"
94
- # 1234567890.to_s(:human) # => "1.23 Billion"
95
- # 1234567890123.to_s(:human) # => "1.23 Trillion"
96
- # 1234567890123456.to_s(:human) # => "1.23 Quadrillion"
97
- # 1234567890123456789.to_s(:human) # => "1230 Quadrillion"
98
- # 489939.to_s(:human, precision: 2) # => "490 Thousand"
99
- # 489939.to_s(:human, precision: 4) # => "489.9 Thousand"
100
- # 1234567.to_s(:human, precision: 4,
101
- # significant: false) # => "1.2346 Million"
102
- # 1234567.to_s(:human, precision: 1,
97
+ # 123.to_fs(:human) # => "123"
98
+ # 1234.to_fs(:human) # => "1.23 Thousand"
99
+ # 12345.to_fs(:human) # => "12.3 Thousand"
100
+ # 1234567.to_fs(:human) # => "1.23 Million"
101
+ # 1234567890.to_fs(:human) # => "1.23 Billion"
102
+ # 1234567890123.to_fs(:human) # => "1.23 Trillion"
103
+ # 1234567890123456.to_fs(:human) # => "1.23 Quadrillion"
104
+ # 1234567890123456789.to_fs(:human) # => "1230 Quadrillion"
105
+ # 489939.to_fs(:human, precision: 2) # => "490 Thousand"
106
+ # 489939.to_fs(:human, precision: 2, round_mode: :down) # => "480 Thousand"
107
+ # 489939.to_fs(:human, precision: 4) # => "489.9 Thousand"
108
+ # 1234567.to_fs(:human, precision: 4,
109
+ # significant: false) # => "1.2346 Million"
110
+ # 1234567.to_fs(:human, precision: 1,
103
111
  # separator: ',',
104
- # significant: false) # => "1,2 Million"
105
- def to_s(format = nil, options = nil)
112
+ # significant: false) # => "1,2 Million"
113
+ def to_fs(format = nil, options = nil)
114
+ return to_s if format.nil?
115
+
106
116
  case format
107
- when nil
108
- super()
109
117
  when Integer, String
110
- super(format)
118
+ to_s(format)
111
119
  when :phone
112
120
  ActiveSupport::NumberHelper.number_to_phone(self, options || {})
113
121
  when :currency
@@ -123,11 +131,12 @@ module ActiveSupport
123
131
  when :human_size
124
132
  ActiveSupport::NumberHelper.number_to_human_size(self, options || {})
125
133
  when Symbol
126
- super()
134
+ to_s
127
135
  else
128
- super(format)
136
+ to_s(format)
129
137
  end
130
138
  end
139
+ alias_method :to_formatted_s, :to_fs
131
140
  end
132
141
  end
133
142
 
@@ -1,11 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Object
4
- # A duck-type assistant method. For example, Active Support extends Date
5
- # to define an <tt>acts_like_date?</tt> method, and extends Time to define
6
- # <tt>acts_like_time?</tt>. As a result, we can do <tt>x.acts_like?(:time)</tt> and
7
- # <tt>x.acts_like?(:date)</tt> to do duck-type-safe comparisons, since classes that
8
- # we want to act like Time simply need to define an <tt>acts_like_time?</tt> method.
4
+ # Provides a way to check whether some class acts like some other class based on the existence of
5
+ # an appropriately-named marker method.
6
+ #
7
+ # A class that provides the same interface as <tt>SomeClass</tt> may define a marker method named
8
+ # <tt>acts_like_some_class?</tt> to signal its compatibility to callers of
9
+ # <tt>acts_like?(:some_class)</tt>.
10
+ #
11
+ # For example, Active Support extends <tt>Date</tt> to define an <tt>acts_like_date?</tt> method,
12
+ # and extends <tt>Time</tt> to define <tt>acts_like_time?</tt>. As a result, developers can call
13
+ # <tt>x.acts_like?(:time)</tt> and <tt>x.acts_like?(:date)</tt> to test duck-type compatibility,
14
+ # and classes that are able to act like <tt>Time</tt> can also define an <tt>acts_like_time?</tt>
15
+ # method to interoperate.
16
+ #
17
+ # Note that the marker method is only expected to exist. It isn't called, so its body or return
18
+ # value are irrelevant.
19
+ #
20
+ # ==== Example: A class that provides the same interface as <tt>String</tt>
21
+ #
22
+ # This class may define:
23
+ #
24
+ # class Stringish
25
+ # def acts_like_string?
26
+ # end
27
+ # end
28
+ #
29
+ # Then client code can query for duck-type-safeness this way:
30
+ #
31
+ # Stringish.new.acts_like?(:string) # => true
32
+ #
9
33
  def acts_like?(duck)
10
34
  case duck
11
35
  when :time
@@ -131,7 +131,7 @@ class String
131
131
  end
132
132
  end
133
133
 
134
- class Numeric #:nodoc:
134
+ class Numeric # :nodoc:
135
135
  # No number is blank:
136
136
  #
137
137
  # 1.blank? # => false
@@ -143,7 +143,7 @@ class Numeric #:nodoc:
143
143
  end
144
144
  end
145
145
 
146
- class Time #:nodoc:
146
+ class Time # :nodoc:
147
147
  # No Time is blank:
148
148
  #
149
149
  # Time.now.blank? # => false
@@ -43,7 +43,7 @@ class Hash
43
43
  def deep_dup
44
44
  hash = dup
45
45
  each_pair do |key, value|
46
- if key.frozen? && ::String === key
46
+ if ::String === key || ::Symbol === key
47
47
  hash[key] = value.deep_dup
48
48
  else
49
49
  hash.delete(key)
@@ -53,3 +53,19 @@ class Hash
53
53
  hash
54
54
  end
55
55
  end
56
+
57
+ class Module
58
+ # Returns a copy of module or class if it's anonymous. If it's
59
+ # named, returns +self+.
60
+ #
61
+ # Object.deep_dup == Object # => true
62
+ # klass = Class.new
63
+ # klass.deep_dup == klass # => false
64
+ def deep_dup
65
+ if name.nil?
66
+ super
67
+ else
68
+ self
69
+ end
70
+ end
71
+ end
@@ -31,8 +31,8 @@ end
31
31
  class Method
32
32
  # Methods are not duplicable:
33
33
  #
34
- # method(:puts).duplicable? # => false
35
- # method(:puts).dup # => TypeError: allocator undefined for Method
34
+ # method(:puts).duplicable? # => false
35
+ # method(:puts).dup # => TypeError: allocator undefined for Method
36
36
  def duplicable?
37
37
  false
38
38
  end
@@ -41,8 +41,19 @@ end
41
41
  class UnboundMethod
42
42
  # Unbound methods are not duplicable:
43
43
  #
44
- # method(:puts).unbind.duplicable? # => false
45
- # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
44
+ # method(:puts).unbind.duplicable? # => false
45
+ # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
46
+ def duplicable?
47
+ false
48
+ end
49
+ end
50
+
51
+ require "singleton"
52
+
53
+ module Singleton
54
+ # Singleton instances are not duplicable:
55
+ #
56
+ # Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
46
57
  def duplicable?
47
58
  false
48
59
  end
@@ -1,16 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Object
4
- # Returns true if this object is included in the argument. Argument must be
5
- # any object which responds to +#include?+. Usage:
4
+ # Returns true if this object is included in the argument.
5
+ #
6
+ # When argument is a +Range+, +#cover?+ is used to properly handle inclusion
7
+ # check within open ranges. Otherwise, argument must be any object which responds
8
+ # to +#include?+. Usage:
6
9
  #
7
10
  # characters = ["Konata", "Kagami", "Tsukasa"]
8
11
  # "Konata".in?(characters) # => true
9
12
  #
10
- # This will throw an +ArgumentError+ if the argument doesn't respond
11
- # to +#include?+.
13
+ # For non +Range+ arguments, this will throw an +ArgumentError+ if the argument
14
+ # doesn't respond to +#include?+.
12
15
  def in?(another_object)
13
- another_object.include?(self)
16
+ case another_object
17
+ when Range
18
+ another_object.cover?(self)
19
+ else
20
+ another_object.include?(self)
21
+ end
14
22
  rescue NoMethodError
15
23
  raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
16
24
  end
@@ -12,19 +12,29 @@ class Object
12
12
  #
13
13
  # C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}
14
14
  def instance_values
15
- Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }]
15
+ instance_variables.to_h do |ivar|
16
+ [ivar[1..-1].freeze, instance_variable_get(ivar)]
17
+ end
16
18
  end
17
19
 
18
- # Returns an array of instance variable names as strings including "@".
19
- #
20
- # class C
21
- # def initialize(x, y)
22
- # @x, @y = x, y
23
- # end
24
- # end
25
- #
26
- # C.new(0, 1).instance_variable_names # => ["@y", "@x"]
27
- def instance_variable_names
28
- instance_variables.map(&:to_s)
20
+ if Symbol.method_defined?(:name) # RUBY_VERSION >= "3.0"
21
+ # Returns an array of instance variable names as strings including "@".
22
+ #
23
+ # class C
24
+ # def initialize(x, y)
25
+ # @x, @y = x, y
26
+ # end
27
+ # end
28
+ #
29
+ # C.new(0, 1).instance_variable_names # => ["@y", "@x"]
30
+ def instance_variable_names
31
+ instance_variables.map(&:name)
32
+ end
33
+ else
34
+ def instance_variable_names
35
+ variables = instance_variables
36
+ variables.map! { |s| s.to_s.freeze }
37
+ variables
38
+ end
29
39
  end
30
40
  end