activesupport 5.2.4.3 → 7.0.3

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.

Potentially problematic release.


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

Files changed (228) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +244 -459
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -3
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/array_inquirer.rb +2 -2
  7. data/lib/active_support/backtrace_cleaner.rb +31 -5
  8. data/lib/active_support/benchmarkable.rb +3 -3
  9. data/lib/active_support/cache/file_store.rb +47 -41
  10. data/lib/active_support/cache/mem_cache_store.rb +151 -40
  11. data/lib/active_support/cache/memory_store.rb +68 -34
  12. data/lib/active_support/cache/null_store.rb +16 -3
  13. data/lib/active_support/cache/redis_cache_store.rb +103 -101
  14. data/lib/active_support/cache/strategy/local_cache.rb +56 -64
  15. data/lib/active_support/cache.rb +333 -116
  16. data/lib/active_support/callbacks.rb +244 -128
  17. data/lib/active_support/code_generator.rb +65 -0
  18. data/lib/active_support/concern.rb +72 -5
  19. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +16 -0
  20. data/lib/active_support/concurrency/share_lock.rb +2 -3
  21. data/lib/active_support/configurable.rb +15 -16
  22. data/lib/active_support/configuration_file.rb +51 -0
  23. data/lib/active_support/core_ext/array/access.rb +15 -7
  24. data/lib/active_support/core_ext/array/conversions.rb +18 -17
  25. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  26. data/lib/active_support/core_ext/array/extract.rb +21 -0
  27. data/lib/active_support/core_ext/array/grouping.rb +6 -6
  28. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  29. data/lib/active_support/core_ext/array.rb +2 -1
  30. data/lib/active_support/core_ext/benchmark.rb +2 -2
  31. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  32. data/lib/active_support/core_ext/class/attribute.rb +32 -47
  33. data/lib/active_support/core_ext/class/subclasses.rb +9 -22
  34. data/lib/active_support/core_ext/date/blank.rb +1 -1
  35. data/lib/active_support/core_ext/date/calculations.rb +15 -14
  36. data/lib/active_support/core_ext/date/conversions.rb +16 -15
  37. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  38. data/lib/active_support/core_ext/date.rb +1 -0
  39. data/lib/active_support/core_ext/date_and_time/calculations.rb +41 -51
  40. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  41. data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
  42. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  43. data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
  44. data/lib/active_support/core_ext/date_time/conversions.rb +13 -14
  45. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  46. data/lib/active_support/core_ext/date_time.rb +1 -0
  47. data/lib/active_support/core_ext/digest/uuid.rb +39 -13
  48. data/lib/active_support/core_ext/enumerable.rb +241 -76
  49. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  50. data/lib/active_support/core_ext/hash/conversions.rb +3 -4
  51. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  52. data/lib/active_support/core_ext/hash/except.rb +2 -2
  53. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  54. data/lib/active_support/core_ext/hash/keys.rb +2 -31
  55. data/lib/active_support/core_ext/hash/slice.rb +6 -27
  56. data/lib/active_support/core_ext/hash.rb +1 -2
  57. data/lib/active_support/core_ext/integer/multiple.rb +1 -1
  58. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  59. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  60. data/lib/active_support/core_ext/kernel.rb +0 -1
  61. data/lib/active_support/core_ext/load_error.rb +1 -1
  62. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  63. data/lib/active_support/core_ext/module/attribute_accessors.rb +32 -39
  64. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +35 -28
  65. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  66. data/lib/active_support/core_ext/module/delegation.rb +70 -33
  67. data/lib/active_support/core_ext/module/introspection.rb +16 -15
  68. data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
  69. data/lib/active_support/core_ext/module.rb +0 -1
  70. data/lib/active_support/core_ext/name_error.rb +23 -2
  71. data/lib/active_support/core_ext/numeric/conversions.rb +132 -129
  72. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  73. data/lib/active_support/core_ext/numeric.rb +1 -1
  74. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  75. data/lib/active_support/core_ext/object/blank.rb +3 -4
  76. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  77. data/lib/active_support/core_ext/object/duplicable.rb +14 -110
  78. data/lib/active_support/core_ext/object/json.rb +44 -27
  79. data/lib/active_support/core_ext/object/to_query.rb +2 -2
  80. data/lib/active_support/core_ext/object/try.rb +24 -14
  81. data/lib/active_support/core_ext/object/with_options.rb +21 -2
  82. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  83. data/lib/active_support/core_ext/pathname.rb +3 -0
  84. data/lib/active_support/core_ext/range/compare_range.rb +23 -27
  85. data/lib/active_support/core_ext/range/conversions.rb +32 -30
  86. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  87. data/lib/active_support/core_ext/range/each.rb +1 -2
  88. data/lib/active_support/core_ext/range/include_time_with_zone.rb +4 -20
  89. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  90. data/lib/active_support/core_ext/range.rb +1 -1
  91. data/lib/active_support/core_ext/regexp.rb +8 -5
  92. data/lib/active_support/core_ext/securerandom.rb +23 -3
  93. data/lib/active_support/core_ext/string/access.rb +5 -16
  94. data/lib/active_support/core_ext/string/conversions.rb +3 -2
  95. data/lib/active_support/core_ext/string/filters.rb +42 -1
  96. data/lib/active_support/core_ext/string/inflections.rb +46 -7
  97. data/lib/active_support/core_ext/string/inquiry.rb +2 -1
  98. data/lib/active_support/core_ext/string/multibyte.rb +6 -5
  99. data/lib/active_support/core_ext/string/output_safety.rb +129 -20
  100. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  101. data/lib/active_support/core_ext/string/strip.rb +3 -1
  102. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  103. data/lib/active_support/core_ext/symbol.rb +3 -0
  104. data/lib/active_support/core_ext/time/calculations.rb +59 -10
  105. data/lib/active_support/core_ext/time/conversions.rb +15 -12
  106. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  107. data/lib/active_support/core_ext/time/zones.rb +7 -22
  108. data/lib/active_support/core_ext/time.rb +1 -0
  109. data/lib/active_support/core_ext/uri.rb +3 -22
  110. data/lib/active_support/core_ext.rb +2 -1
  111. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  112. data/lib/active_support/current_attributes.rb +47 -16
  113. data/lib/active_support/dependencies/interlock.rb +10 -18
  114. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  115. data/lib/active_support/dependencies.rb +60 -715
  116. data/lib/active_support/deprecation/behaviors.rb +21 -5
  117. data/lib/active_support/deprecation/disallowed.rb +56 -0
  118. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  119. data/lib/active_support/deprecation/method_wrappers.rb +18 -23
  120. data/lib/active_support/deprecation/proxy_wrappers.rb +31 -8
  121. data/lib/active_support/deprecation/reporting.rb +50 -7
  122. data/lib/active_support/deprecation.rb +7 -2
  123. data/lib/active_support/descendants_tracker.rb +190 -34
  124. data/lib/active_support/digest.rb +5 -3
  125. data/lib/active_support/duration/iso8601_parser.rb +5 -7
  126. data/lib/active_support/duration/iso8601_serializer.rb +27 -15
  127. data/lib/active_support/duration.rb +149 -67
  128. data/lib/active_support/encrypted_configuration.rb +12 -5
  129. data/lib/active_support/encrypted_file.rb +23 -5
  130. data/lib/active_support/environment_inquirer.rb +20 -0
  131. data/lib/active_support/error_reporter.rb +117 -0
  132. data/lib/active_support/evented_file_update_checker.rb +85 -122
  133. data/lib/active_support/execution_context/test_helper.rb +13 -0
  134. data/lib/active_support/execution_context.rb +53 -0
  135. data/lib/active_support/execution_wrapper.rb +44 -21
  136. data/lib/active_support/executor/test_helper.rb +7 -0
  137. data/lib/active_support/file_update_checker.rb +0 -1
  138. data/lib/active_support/fork_tracker.rb +71 -0
  139. data/lib/active_support/gem_version.rb +5 -5
  140. data/lib/active_support/hash_with_indifferent_access.rb +73 -43
  141. data/lib/active_support/html_safe_translation.rb +43 -0
  142. data/lib/active_support/i18n.rb +2 -0
  143. data/lib/active_support/i18n_railtie.rb +15 -8
  144. data/lib/active_support/inflector/inflections.rb +25 -14
  145. data/lib/active_support/inflector/methods.rb +38 -71
  146. data/lib/active_support/inflector/transliterate.rb +47 -18
  147. data/lib/active_support/isolated_execution_state.rb +72 -0
  148. data/lib/active_support/json/decoding.rb +25 -26
  149. data/lib/active_support/json/encoding.rb +14 -6
  150. data/lib/active_support/key_generator.rb +23 -38
  151. data/lib/active_support/lazy_load_hooks.rb +19 -5
  152. data/lib/active_support/locale/en.rb +33 -0
  153. data/lib/active_support/locale/en.yml +8 -4
  154. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  155. data/lib/active_support/log_subscriber.rb +51 -11
  156. data/lib/active_support/logger.rb +6 -22
  157. data/lib/active_support/logger_silence.rb +11 -19
  158. data/lib/active_support/logger_thread_safe_level.rb +45 -10
  159. data/lib/active_support/message_encryptor.rb +20 -19
  160. data/lib/active_support/message_verifier.rb +53 -21
  161. data/lib/active_support/messages/metadata.rb +13 -4
  162. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  163. data/lib/active_support/messages/rotator.rb +10 -9
  164. data/lib/active_support/multibyte/chars.rb +17 -76
  165. data/lib/active_support/multibyte/unicode.rb +7 -331
  166. data/lib/active_support/multibyte.rb +1 -1
  167. data/lib/active_support/notifications/fanout.rb +163 -37
  168. data/lib/active_support/notifications/instrumenter.rb +90 -11
  169. data/lib/active_support/notifications.rb +88 -30
  170. data/lib/active_support/number_helper/number_converter.rb +6 -9
  171. data/lib/active_support/number_helper/number_to_currency_converter.rb +12 -12
  172. data/lib/active_support/number_helper/number_to_delimited_converter.rb +4 -3
  173. data/lib/active_support/number_helper/number_to_human_converter.rb +4 -3
  174. data/lib/active_support/number_helper/number_to_human_size_converter.rb +5 -4
  175. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  176. data/lib/active_support/number_helper/number_to_phone_converter.rb +3 -2
  177. data/lib/active_support/number_helper/number_to_rounded_converter.rb +12 -7
  178. data/lib/active_support/number_helper/rounding_helper.rb +12 -32
  179. data/lib/active_support/number_helper.rb +36 -12
  180. data/lib/active_support/option_merger.rb +15 -4
  181. data/lib/active_support/ordered_hash.rb +2 -2
  182. data/lib/active_support/ordered_options.rb +14 -4
  183. data/lib/active_support/parameter_filter.rb +138 -0
  184. data/lib/active_support/per_thread_registry.rb +6 -1
  185. data/lib/active_support/rails.rb +1 -10
  186. data/lib/active_support/railtie.rb +77 -5
  187. data/lib/active_support/reloader.rb +5 -6
  188. data/lib/active_support/rescuable.rb +8 -8
  189. data/lib/active_support/ruby_features.rb +7 -0
  190. data/lib/active_support/secure_compare_rotator.rb +51 -0
  191. data/lib/active_support/security_utils.rb +19 -12
  192. data/lib/active_support/string_inquirer.rb +2 -3
  193. data/lib/active_support/subscriber.rb +79 -46
  194. data/lib/active_support/tagged_logging.rb +58 -9
  195. data/lib/active_support/test_case.rb +79 -0
  196. data/lib/active_support/testing/assertions.rb +62 -11
  197. data/lib/active_support/testing/deprecation.rb +52 -2
  198. data/lib/active_support/testing/file_fixtures.rb +2 -0
  199. data/lib/active_support/testing/isolation.rb +4 -4
  200. data/lib/active_support/testing/method_call_assertions.rb +32 -5
  201. data/lib/active_support/testing/parallelization/server.rb +82 -0
  202. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  203. data/lib/active_support/testing/parallelization.rb +55 -0
  204. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  205. data/lib/active_support/testing/stream.rb +4 -7
  206. data/lib/active_support/testing/tagged_logging.rb +1 -1
  207. data/lib/active_support/testing/time_helpers.rb +60 -14
  208. data/lib/active_support/time_with_zone.rb +139 -64
  209. data/lib/active_support/values/time_zone.rb +66 -30
  210. data/lib/active_support/version.rb +1 -1
  211. data/lib/active_support/xml_mini/jdom.rb +3 -4
  212. data/lib/active_support/xml_mini/libxml.rb +7 -7
  213. data/lib/active_support/xml_mini/libxmlsax.rb +5 -5
  214. data/lib/active_support/xml_mini/nokogiri.rb +6 -6
  215. data/lib/active_support/xml_mini/nokogirisax.rb +4 -4
  216. data/lib/active_support/xml_mini/rexml.rb +11 -4
  217. data/lib/active_support/xml_mini.rb +7 -14
  218. data/lib/active_support.rb +30 -1
  219. metadata +64 -35
  220. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -9
  221. data/lib/active_support/core_ext/hash/compact.rb +0 -29
  222. data/lib/active_support/core_ext/hash/transform_values.rb +0 -32
  223. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
  224. data/lib/active_support/core_ext/marshal.rb +0 -24
  225. data/lib/active_support/core_ext/module/reachable.rb +0 -11
  226. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -28
  227. data/lib/active_support/core_ext/range/include_range.rb +0 -3
  228. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,16 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/string/filters"
3
4
  require "active_support/inflector"
4
5
 
5
6
  class Module
6
7
  # Returns the name of the module containing this one.
7
8
  #
8
- # M::N.parent_name # => "M"
9
- def parent_name
9
+ # M::N.module_parent_name # => "M"
10
+ def module_parent_name
10
11
  if defined?(@parent_name)
11
12
  @parent_name
12
13
  else
13
- parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
14
+ parent_name = name =~ /::[^:]+\z/ ? -$` : nil
14
15
  @parent_name = parent_name unless frozen?
15
16
  parent_name
16
17
  end
@@ -24,15 +25,15 @@ class Module
24
25
  # end
25
26
  # X = M::N
26
27
  #
27
- # M::N.parent # => M
28
- # X.parent # => M
28
+ # M::N.module_parent # => M
29
+ # X.module_parent # => M
29
30
  #
30
31
  # The parent of top-level and anonymous modules is Object.
31
32
  #
32
- # M.parent # => Object
33
- # Module.new.parent # => Object
34
- def parent
35
- parent_name ? ActiveSupport::Inflector.constantize(parent_name) : Object
33
+ # M.module_parent # => Object
34
+ # Module.new.module_parent # => Object
35
+ def module_parent
36
+ module_parent_name ? ActiveSupport::Inflector.constantize(module_parent_name) : Object
36
37
  end
37
38
 
38
39
  # Returns all the parents of this module according to its name, ordered from
@@ -44,13 +45,13 @@ class Module
44
45
  # end
45
46
  # X = M::N
46
47
  #
47
- # M.parents # => [Object]
48
- # M::N.parents # => [M, Object]
49
- # X.parents # => [M, Object]
50
- def parents
48
+ # M.module_parents # => [Object]
49
+ # M::N.module_parents # => [M, Object]
50
+ # X.module_parents # => [M, Object]
51
+ def module_parents
51
52
  parents = []
52
- if parent_name
53
- parts = parent_name.split("::")
53
+ if module_parent_name
54
+ parts = module_parent_name.split("::")
54
55
  until parts.empty?
55
56
  parents << ActiveSupport::Inflector.constantize(parts * "::")
56
57
  parts.pop
@@ -1,23 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Module
4
- if RUBY_VERSION >= "2.3"
5
- # Marks the named method as intended to be redefined, if it exists.
6
- # Suppresses the Ruby method redefinition warning. Prefer
7
- # #redefine_method where possible.
8
- def silence_redefinition_of_method(method)
9
- if method_defined?(method) || private_method_defined?(method)
10
- # This suppresses the "method redefined" warning; the self-alias
11
- # looks odd, but means we don't need to generate a unique name
12
- alias_method method, method
13
- end
14
- end
15
- else
16
- def silence_redefinition_of_method(method)
17
- if method_defined?(method) || private_method_defined?(method)
18
- alias_method :__rails_redefine, method
19
- remove_method :__rails_redefine
20
- end
4
+ # Marks the named method as intended to be redefined, if it exists.
5
+ # Suppresses the Ruby method redefinition warning. Prefer
6
+ # #redefine_method where possible.
7
+ def silence_redefinition_of_method(method)
8
+ if method_defined?(method) || private_method_defined?(method)
9
+ # This suppresses the "method redefined" warning; the self-alias
10
+ # looks odd, but means we don't need to generate a unique name
11
+ alias_method method, method
21
12
  end
22
13
  end
23
14
 
@@ -3,7 +3,6 @@
3
3
  require "active_support/core_ext/module/aliasing"
4
4
  require "active_support/core_ext/module/introspection"
5
5
  require "active_support/core_ext/module/anonymous"
6
- require "active_support/core_ext/module/reachable"
7
6
  require "active_support/core_ext/module/attribute_accessors"
8
7
  require "active_support/core_ext/module/attribute_accessors_per_thread"
9
8
  require "active_support/core_ext/module/attr_internal"
@@ -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
@@ -2,139 +2,142 @@
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
- module ActiveSupport::NumericWithFormat
8
- # Provides options for converting numbers into formatted strings.
9
- # Options are provided for phone numbers, currency, percentage,
10
- # precision, positional notation, file size and pretty printing.
11
- #
12
- # ==== Options
13
- #
14
- # For details on which formats use which options, see ActiveSupport::NumberHelper
15
- #
16
- # ==== Examples
17
- #
18
- # Phone Numbers:
19
- # 5551234.to_s(:phone) # => "555-1234"
20
- # 1235551234.to_s(:phone) # => "123-555-1234"
21
- # 1235551234.to_s(:phone, area_code: true) # => "(123) 555-1234"
22
- # 1235551234.to_s(:phone, delimiter: ' ') # => "123 555 1234"
23
- # 1235551234.to_s(:phone, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
24
- # 1235551234.to_s(:phone, country_code: 1) # => "+1-123-555-1234"
25
- # 1235551234.to_s(:phone, country_code: 1, extension: 1343, delimiter: '.')
26
- # # => "+1.123.555.1234 x 1343"
27
- #
28
- # Currency:
29
- # 1234567890.50.to_s(:currency) # => "$1,234,567,890.50"
30
- # 1234567890.506.to_s(:currency) # => "$1,234,567,890.51"
31
- # 1234567890.506.to_s(:currency, precision: 3) # => "$1,234,567,890.506"
32
- # 1234567890.506.to_s(:currency, locale: :fr) # => "1 234 567 890,51 €"
33
- # -1234567890.50.to_s(:currency, negative_format: '(%u%n)')
34
- # # => "($1,234,567,890.50)"
35
- # 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '')
36
- # # => "&pound;1234567890,50"
37
- # 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
38
- # # => "1234567890,50 &pound;"
39
- #
40
- # Percentage:
41
- # 100.to_s(:percentage) # => "100.000%"
42
- # 100.to_s(:percentage, precision: 0) # => "100%"
43
- # 1000.to_s(:percentage, delimiter: '.', separator: ',') # => "1.000,000%"
44
- # 302.24398923423.to_s(:percentage, precision: 5) # => "302.24399%"
45
- # 1000.to_s(:percentage, locale: :fr) # => "1 000,000%"
46
- # 100.to_s(:percentage, format: '%n %') # => "100.000 %"
47
- #
48
- # Delimited:
49
- # 12345678.to_s(:delimited) # => "12,345,678"
50
- # 12345678.05.to_s(:delimited) # => "12,345,678.05"
51
- # 12345678.to_s(:delimited, delimiter: '.') # => "12.345.678"
52
- # 12345678.to_s(:delimited, delimiter: ',') # => "12,345,678"
53
- # 12345678.05.to_s(:delimited, separator: ' ') # => "12,345,678 05"
54
- # 12345678.05.to_s(:delimited, locale: :fr) # => "12 345 678,05"
55
- # 98765432.98.to_s(:delimited, delimiter: ' ', separator: ',')
56
- # # => "98 765 432,98"
57
- #
58
- # Rounded:
59
- # 111.2345.to_s(:rounded) # => "111.235"
60
- # 111.2345.to_s(:rounded, precision: 2) # => "111.23"
61
- # 13.to_s(:rounded, precision: 5) # => "13.00000"
62
- # 389.32314.to_s(:rounded, precision: 0) # => "389"
63
- # 111.2345.to_s(:rounded, significant: true) # => "111"
64
- # 111.2345.to_s(:rounded, precision: 1, significant: true) # => "100"
65
- # 13.to_s(:rounded, precision: 5, significant: true) # => "13.000"
66
- # 111.234.to_s(:rounded, locale: :fr) # => "111,234"
67
- # 13.to_s(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true)
68
- # # => "13"
69
- # 389.32314.to_s(:rounded, precision: 4, significant: true) # => "389.3"
70
- # 1111.2345.to_s(:rounded, precision: 2, separator: ',', delimiter: '.')
71
- # # => "1.111,23"
72
- #
73
- # Human-friendly size in Bytes:
74
- # 123.to_s(:human_size) # => "123 Bytes"
75
- # 1234.to_s(:human_size) # => "1.21 KB"
76
- # 12345.to_s(:human_size) # => "12.1 KB"
77
- # 1234567.to_s(:human_size) # => "1.18 MB"
78
- # 1234567890.to_s(:human_size) # => "1.15 GB"
79
- # 1234567890123.to_s(:human_size) # => "1.12 TB"
80
- # 1234567890123456.to_s(:human_size) # => "1.1 PB"
81
- # 1234567890123456789.to_s(:human_size) # => "1.07 EB"
82
- # 1234567.to_s(:human_size, precision: 2) # => "1.2 MB"
83
- # 483989.to_s(:human_size, precision: 2) # => "470 KB"
84
- # 1234567.to_s(:human_size, precision: 2, separator: ',') # => "1,2 MB"
85
- # 1234567890123.to_s(:human_size, precision: 5) # => "1.1228 TB"
86
- # 524288000.to_s(:human_size, precision: 5) # => "500 MB"
87
- #
88
- # Human-friendly format:
89
- # 123.to_s(:human) # => "123"
90
- # 1234.to_s(:human) # => "1.23 Thousand"
91
- # 12345.to_s(:human) # => "12.3 Thousand"
92
- # 1234567.to_s(:human) # => "1.23 Million"
93
- # 1234567890.to_s(:human) # => "1.23 Billion"
94
- # 1234567890123.to_s(:human) # => "1.23 Trillion"
95
- # 1234567890123456.to_s(:human) # => "1.23 Quadrillion"
96
- # 1234567890123456789.to_s(:human) # => "1230 Quadrillion"
97
- # 489939.to_s(:human, precision: 2) # => "490 Thousand"
98
- # 489939.to_s(:human, precision: 4) # => "489.9 Thousand"
99
- # 1234567.to_s(:human, precision: 4,
100
- # significant: false) # => "1.2346 Million"
101
- # 1234567.to_s(:human, precision: 1,
102
- # separator: ',',
103
- # significant: false) # => "1,2 Million"
104
- def to_s(format = nil, options = nil)
105
- case format
106
- when nil
107
- super()
108
- when Integer, String
109
- super(format)
110
- when :phone
111
- ActiveSupport::NumberHelper.number_to_phone(self, options || {})
112
- when :currency
113
- ActiveSupport::NumberHelper.number_to_currency(self, options || {})
114
- when :percentage
115
- ActiveSupport::NumberHelper.number_to_percentage(self, options || {})
116
- when :delimited
117
- ActiveSupport::NumberHelper.number_to_delimited(self, options || {})
118
- when :rounded
119
- ActiveSupport::NumberHelper.number_to_rounded(self, options || {})
120
- when :human
121
- ActiveSupport::NumberHelper.number_to_human(self, options || {})
122
- when :human_size
123
- ActiveSupport::NumberHelper.number_to_human_size(self, options || {})
124
- when Symbol
125
- super()
126
- else
127
- super(format)
6
+ module ActiveSupport
7
+ module NumericWithFormat
8
+ # Provides options for converting numbers into formatted strings.
9
+ # Options are provided for phone numbers, currency, percentage,
10
+ # precision, positional notation, file size, and pretty printing.
11
+ #
12
+ # This method is aliased to <tt>to_formatted_s</tt>.
13
+ #
14
+ # ==== Options
15
+ #
16
+ # For details on which formats use which options, see ActiveSupport::NumberHelper
17
+ #
18
+ # ==== Examples
19
+ #
20
+ # Phone Numbers:
21
+ # 5551234.to_fs(:phone) # => "555-1234"
22
+ # 1235551234.to_fs(:phone) # => "123-555-1234"
23
+ # 1235551234.to_fs(:phone, area_code: true) # => "(123) 555-1234"
24
+ # 1235551234.to_fs(:phone, delimiter: ' ') # => "123 555 1234"
25
+ # 1235551234.to_fs(:phone, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
26
+ # 1235551234.to_fs(:phone, country_code: 1) # => "+1-123-555-1234"
27
+ # 1235551234.to_fs(:phone, country_code: 1, extension: 1343, delimiter: '.')
28
+ # # => "+1.123.555.1234 x 1343"
29
+ #
30
+ # Currency:
31
+ # 1234567890.50.to_fs(:currency) # => "$1,234,567,890.50"
32
+ # 1234567890.506.to_fs(:currency) # => "$1,234,567,890.51"
33
+ # 1234567890.506.to_fs(:currency, precision: 3) # => "$1,234,567,890.506"
34
+ # 1234567890.506.to_fs(:currency, round_mode: :down) # => "$1,234,567,890.50"
35
+ # 1234567890.506.to_fs(:currency, locale: :fr) # => "1 234 567 890,51 €"
36
+ # -1234567890.50.to_fs(:currency, negative_format: '(%u%n)')
37
+ # # => "($1,234,567,890.50)"
38
+ # 1234567890.50.to_fs(:currency, unit: '&pound;', separator: ',', delimiter: '')
39
+ # # => "&pound;1234567890,50"
40
+ # 1234567890.50.to_fs(:currency, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
41
+ # # => "1234567890,50 &pound;"
42
+ #
43
+ # Percentage:
44
+ # 100.to_fs(:percentage) # => "100.000%"
45
+ # 100.to_fs(:percentage, precision: 0) # => "100%"
46
+ # 1000.to_fs(:percentage, delimiter: '.', separator: ',') # => "1.000,000%"
47
+ # 302.24398923423.to_fs(:percentage, precision: 5) # => "302.24399%"
48
+ # 302.24398923423.to_fs(:percentage, round_mode: :down) # => "302.243%"
49
+ # 1000.to_fs(:percentage, locale: :fr) # => "1 000,000%"
50
+ # 100.to_fs(:percentage, format: '%n %') # => "100.000 %"
51
+ #
52
+ # Delimited:
53
+ # 12345678.to_fs(:delimited) # => "12,345,678"
54
+ # 12345678.05.to_fs(:delimited) # => "12,345,678.05"
55
+ # 12345678.to_fs(:delimited, delimiter: '.') # => "12.345.678"
56
+ # 12345678.to_fs(:delimited, delimiter: ',') # => "12,345,678"
57
+ # 12345678.05.to_fs(:delimited, separator: ' ') # => "12,345,678 05"
58
+ # 12345678.05.to_fs(:delimited, locale: :fr) # => "12 345 678,05"
59
+ # 98765432.98.to_fs(:delimited, delimiter: ' ', separator: ',')
60
+ # # => "98 765 432,98"
61
+ #
62
+ # Rounded:
63
+ # 111.2345.to_fs(:rounded) # => "111.235"
64
+ # 111.2345.to_fs(:rounded, precision: 2) # => "111.23"
65
+ # 111.2345.to_fs(:rounded, precision: 2, round_mode: :up) # => "111.24"
66
+ # 13.to_fs(:rounded, precision: 5) # => "13.00000"
67
+ # 389.32314.to_fs(:rounded, precision: 0) # => "389"
68
+ # 111.2345.to_fs(:rounded, significant: true) # => "111"
69
+ # 111.2345.to_fs(:rounded, precision: 1, significant: true) # => "100"
70
+ # 13.to_fs(:rounded, precision: 5, significant: true) # => "13.000"
71
+ # 111.234.to_fs(:rounded, locale: :fr) # => "111,234"
72
+ # 13.to_fs(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true)
73
+ # # => "13"
74
+ # 389.32314.to_fs(:rounded, precision: 4, significant: true) # => "389.3"
75
+ # 1111.2345.to_fs(:rounded, precision: 2, separator: ',', delimiter: '.')
76
+ # # => "1.111,23"
77
+ #
78
+ # Human-friendly size in Bytes:
79
+ # 123.to_fs(:human_size) # => "123 Bytes"
80
+ # 1234.to_fs(:human_size) # => "1.21 KB"
81
+ # 12345.to_fs(:human_size) # => "12.1 KB"
82
+ # 1234567.to_fs(:human_size) # => "1.18 MB"
83
+ # 1234567890.to_fs(:human_size) # => "1.15 GB"
84
+ # 1234567890123.to_fs(:human_size) # => "1.12 TB"
85
+ # 1234567890123456.to_fs(:human_size) # => "1.1 PB"
86
+ # 1234567890123456789.to_fs(:human_size) # => "1.07 EB"
87
+ # 1234567.to_fs(:human_size, precision: 2) # => "1.2 MB"
88
+ # 1234567.to_fs(:human_size, precision: 2, round_mode: :up) # => "1.3 MB"
89
+ # 483989.to_fs(:human_size, precision: 2) # => "470 KB"
90
+ # 1234567.to_fs(:human_size, precision: 2, separator: ',') # => "1,2 MB"
91
+ # 1234567890123.to_fs(:human_size, precision: 5) # => "1.1228 TB"
92
+ # 524288000.to_fs(:human_size, precision: 5) # => "500 MB"
93
+ #
94
+ # Human-friendly format:
95
+ # 123.to_fs(:human) # => "123"
96
+ # 1234.to_fs(:human) # => "1.23 Thousand"
97
+ # 12345.to_fs(:human) # => "12.3 Thousand"
98
+ # 1234567.to_fs(:human) # => "1.23 Million"
99
+ # 1234567890.to_fs(:human) # => "1.23 Billion"
100
+ # 1234567890123.to_fs(:human) # => "1.23 Trillion"
101
+ # 1234567890123456.to_fs(:human) # => "1.23 Quadrillion"
102
+ # 1234567890123456789.to_fs(:human) # => "1230 Quadrillion"
103
+ # 489939.to_fs(:human, precision: 2) # => "490 Thousand"
104
+ # 489939.to_fs(:human, precision: 2, round_mode: :down) # => "480 Thousand"
105
+ # 489939.to_fs(:human, precision: 4) # => "489.9 Thousand"
106
+ # 1234567.to_fs(:human, precision: 4,
107
+ # significant: false) # => "1.2346 Million"
108
+ # 1234567.to_fs(:human, precision: 1,
109
+ # separator: ',',
110
+ # significant: false) # => "1,2 Million"
111
+ def to_fs(format = nil, options = nil)
112
+ return to_s if format.nil?
113
+
114
+ case format
115
+ when Integer, String
116
+ to_s(format)
117
+ when :phone
118
+ ActiveSupport::NumberHelper.number_to_phone(self, options || {})
119
+ when :currency
120
+ ActiveSupport::NumberHelper.number_to_currency(self, options || {})
121
+ when :percentage
122
+ ActiveSupport::NumberHelper.number_to_percentage(self, options || {})
123
+ when :delimited
124
+ ActiveSupport::NumberHelper.number_to_delimited(self, options || {})
125
+ when :rounded
126
+ ActiveSupport::NumberHelper.number_to_rounded(self, options || {})
127
+ when :human
128
+ ActiveSupport::NumberHelper.number_to_human(self, options || {})
129
+ when :human_size
130
+ ActiveSupport::NumberHelper.number_to_human_size(self, options || {})
131
+ when Symbol
132
+ to_s
133
+ else
134
+ to_s(format)
135
+ end
128
136
  end
137
+ alias_method :to_formatted_s, :to_fs
129
138
  end
130
139
  end
131
140
 
132
- # Ruby 2.4+ unifies Fixnum & Bignum into Integer.
133
- if 0.class == Integer
134
- Integer.prepend ActiveSupport::NumericWithFormat
135
- else
136
- Fixnum.prepend ActiveSupport::NumericWithFormat
137
- Bignum.prepend ActiveSupport::NumericWithFormat
138
- end
141
+ Integer.prepend ActiveSupport::NumericWithFormat
139
142
  Float.prepend ActiveSupport::NumericWithFormat
140
143
  BigDecimal.prepend ActiveSupport::NumericWithFormat
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module DeprecatedNumericWithFormat # :nodoc:
5
+ def to_s(format = nil, options = nil)
6
+ return super() if format.nil?
7
+
8
+ case format
9
+ when Integer, String
10
+ super(format)
11
+ when :phone
12
+ ActiveSupport::Deprecation.warn(
13
+ "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_fs(#{format.inspect}) instead."
14
+ )
15
+ ActiveSupport::NumberHelper.number_to_phone(self, options || {})
16
+ when :currency
17
+ ActiveSupport::Deprecation.warn(
18
+ "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_fs(#{format.inspect}) instead."
19
+ )
20
+ ActiveSupport::NumberHelper.number_to_currency(self, options || {})
21
+ when :percentage
22
+ ActiveSupport::Deprecation.warn(
23
+ "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_fs(#{format.inspect}) instead."
24
+ )
25
+ ActiveSupport::NumberHelper.number_to_percentage(self, options || {})
26
+ when :delimited
27
+ ActiveSupport::Deprecation.warn(
28
+ "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_fs(#{format.inspect}) instead."
29
+ )
30
+ ActiveSupport::NumberHelper.number_to_delimited(self, options || {})
31
+ when :rounded
32
+ ActiveSupport::Deprecation.warn(
33
+ "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_fs(#{format.inspect}) instead."
34
+ )
35
+ ActiveSupport::NumberHelper.number_to_rounded(self, options || {})
36
+ when :human
37
+ ActiveSupport::Deprecation.warn(
38
+ "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_fs(#{format.inspect}) instead."
39
+ )
40
+ ActiveSupport::NumberHelper.number_to_human(self, options || {})
41
+ when :human_size
42
+ ActiveSupport::Deprecation.warn(
43
+ "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_fs(#{format.inspect}) instead."
44
+ )
45
+ ActiveSupport::NumberHelper.number_to_human_size(self, options || {})
46
+ when Symbol
47
+ ActiveSupport::Deprecation.warn(
48
+ "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_fs(#{format.inspect}) instead."
49
+ )
50
+ super()
51
+ else
52
+ super(format)
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ Integer.prepend ActiveSupport::DeprecatedNumericWithFormat
59
+ Float.prepend ActiveSupport::DeprecatedNumericWithFormat
60
+ BigDecimal.prepend ActiveSupport::DeprecatedNumericWithFormat
@@ -2,5 +2,5 @@
2
2
 
3
3
  require "active_support/core_ext/numeric/bytes"
4
4
  require "active_support/core_ext/numeric/time"
5
- require "active_support/core_ext/numeric/inquiry"
6
5
  require "active_support/core_ext/numeric/conversions"
6
+ require "active_support/core_ext/numeric/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"]
@@ -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
@@ -1,11 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/regexp"
4
3
  require "concurrent/map"
5
4
 
6
5
  class Object
7
6
  # An object is blank if it's false, empty, or a whitespace string.
8
- # For example, +false+, '', ' ', +nil+, [], and {} are all blank.
7
+ # For example, +nil+, '', ' ', [], {}, and +false+ are all blank.
9
8
  #
10
9
  # This simplifies
11
10
  #
@@ -132,7 +131,7 @@ class String
132
131
  end
133
132
  end
134
133
 
135
- class Numeric #:nodoc:
134
+ class Numeric # :nodoc:
136
135
  # No number is blank:
137
136
  #
138
137
  # 1.blank? # => false
@@ -144,7 +143,7 @@ class Numeric #:nodoc:
144
143
  end
145
144
  end
146
145
 
147
- class Time #:nodoc:
146
+ class Time # :nodoc:
148
147
  # No Time is blank:
149
148
  #
150
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)