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
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Array
4
+ NOT_SET = Object.new # :nodoc:
5
+ def to_s(format = NOT_SET) # :nodoc:
6
+ case format
7
+ when :db
8
+ ActiveSupport::Deprecation.warn(
9
+ "Array#to_s(#{format.inspect}) is deprecated. Please use Array#to_fs(#{format.inspect}) instead."
10
+ )
11
+ if empty?
12
+ "null"
13
+ else
14
+ collect(&:id).join(",")
15
+ end
16
+ when NOT_SET
17
+ to_default_s
18
+ else
19
+ ActiveSupport::Deprecation.warn(
20
+ "Array#to_s(#{format.inspect}) is deprecated. Please use Array#to_fs(#{format.inspect}) instead."
21
+ )
22
+ to_default_s
23
+ end
24
+ end
25
+ end
@@ -19,7 +19,7 @@ class Array
19
19
  # ["1", "2"]
20
20
  # ["3", "4"]
21
21
  # ["5"]
22
- def in_groups_of(number, fill_with = nil)
22
+ def in_groups_of(number, fill_with = nil, &block)
23
23
  if number.to_i <= 0
24
24
  raise ArgumentError,
25
25
  "Group size must be a positive integer, was #{number.inspect}"
@@ -36,7 +36,7 @@ class Array
36
36
  end
37
37
 
38
38
  if block_given?
39
- collection.each_slice(number) { |slice| yield(slice) }
39
+ collection.each_slice(number, &block)
40
40
  else
41
41
  collection.each_slice(number).to_a
42
42
  end
@@ -59,7 +59,7 @@ class Array
59
59
  # ["1", "2", "3"]
60
60
  # ["4", "5"]
61
61
  # ["6", "7"]
62
- def in_groups(number, fill_with = nil)
62
+ def in_groups(number, fill_with = nil, &block)
63
63
  # size.div number gives minor group size;
64
64
  # size % number gives how many objects need extra accommodation;
65
65
  # each group hold either division or division + 1 items.
@@ -79,7 +79,7 @@ class Array
79
79
  end
80
80
 
81
81
  if block_given?
82
- groups.each { |g| yield(g) }
82
+ groups.each(&block)
83
83
  else
84
84
  groups
85
85
  end
@@ -90,11 +90,11 @@ class Array
90
90
  #
91
91
  # [1, 2, 3, 4, 5].split(3) # => [[1, 2], [4, 5]]
92
92
  # (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
93
- def split(value = nil)
93
+ def split(value = nil, &block)
94
94
  arr = dup
95
95
  result = []
96
96
  if block_given?
97
- while (idx = arr.index { |i| yield i })
97
+ while (idx = arr.index(&block))
98
98
  result << arr.shift(idx)
99
99
  arr.shift
100
100
  end
@@ -3,8 +3,8 @@
3
3
  require "active_support/array_inquirer"
4
4
 
5
5
  class Array
6
- # Wraps the array in an +ArrayInquirer+ object, which gives a friendlier way
7
- # to check its string-like contents.
6
+ # Wraps the array in an ActiveSupport::ArrayInquirer object, which gives a
7
+ # friendlier way to check its string-like contents.
8
8
  #
9
9
  # pets = [:cat, :dog].inquiry
10
10
  #
@@ -3,6 +3,7 @@
3
3
  require "active_support/core_ext/array/wrap"
4
4
  require "active_support/core_ext/array/access"
5
5
  require "active_support/core_ext/array/conversions"
6
+ require "active_support/core_ext/array/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"]
6
7
  require "active_support/core_ext/array/extract"
7
8
  require "active_support/core_ext/array/extract_options"
8
9
  require "active_support/core_ext/array/grouping"
@@ -4,7 +4,7 @@ require "bigdecimal"
4
4
  require "bigdecimal/util"
5
5
 
6
6
  module ActiveSupport
7
- module BigDecimalWithDefaultFormat #:nodoc:
7
+ module BigDecimalWithDefaultFormat # :nodoc:
8
8
  def to_s(format = "F")
9
9
  super(format)
10
10
  end
@@ -1,22 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/ruby_features"
4
+
3
5
  class Class
4
- # Returns an array with all classes that are < than its receiver.
5
- #
6
- # class C; end
7
- # C.descendants # => []
8
- #
9
- # class B < C; end
10
- # C.descendants # => [B]
11
- #
12
- # class A < B; end
13
- # C.descendants # => [B, A]
14
- #
15
- # class D < C; end
16
- # C.descendants # => [B, A, D]
17
- def descendants
18
- ObjectSpace.each_object(singleton_class).reject do |k|
19
- k.singleton_class? || k == self
6
+ if ActiveSupport::RubyFeatures::CLASS_SUBCLASSES
7
+ # Returns an array with all classes that are < than its receiver.
8
+ #
9
+ # class C; end
10
+ # C.descendants # => []
11
+ #
12
+ # class B < C; end
13
+ # C.descendants # => [B]
14
+ #
15
+ # class A < B; end
16
+ # C.descendants # => [B, A]
17
+ #
18
+ # class D < C; end
19
+ # C.descendants # => [B, A, D]
20
+ def descendants
21
+ subclasses.concat(subclasses.flat_map(&:descendants))
22
+ end
23
+ else
24
+ def descendants
25
+ ObjectSpace.each_object(singleton_class).reject do |k|
26
+ k.singleton_class? || k == self
27
+ end
20
28
  end
21
29
  end
22
30
 
@@ -29,5 +37,5 @@ class Class
29
37
  # Foo.subclasses # => [Bar]
30
38
  def subclasses
31
39
  descendants.select { |descendant| descendant.superclass == self }
32
- end
40
+ end unless ActiveSupport::RubyFeatures::CLASS_SUBCLASSES
33
41
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "date"
4
4
 
5
- class Date #:nodoc:
5
+ class Date # :nodoc:
6
6
  # No Date is blank:
7
7
  #
8
8
  # Date.today.blank? # => false
@@ -13,22 +13,22 @@ class Date
13
13
  class << self
14
14
  attr_accessor :beginning_of_week_default
15
15
 
16
- # Returns the week start (e.g. :monday) for the current request, if this has been set (via Date.beginning_of_week=).
16
+ # Returns the week start (e.g. +:monday+) for the current request, if this has been set (via Date.beginning_of_week=).
17
17
  # If <tt>Date.beginning_of_week</tt> has not been set for the current request, returns the week start specified in <tt>config.beginning_of_week</tt>.
18
- # If no config.beginning_of_week was specified, returns :monday.
18
+ # If no +config.beginning_of_week+ was specified, returns +:monday+.
19
19
  def beginning_of_week
20
- Thread.current[:beginning_of_week] || beginning_of_week_default || :monday
20
+ ::ActiveSupport::IsolatedExecutionState[:beginning_of_week] || beginning_of_week_default || :monday
21
21
  end
22
22
 
23
- # Sets <tt>Date.beginning_of_week</tt> to a week start (e.g. :monday) for current request/thread.
23
+ # Sets <tt>Date.beginning_of_week</tt> to a week start (e.g. +:monday+) for current request/thread.
24
24
  #
25
25
  # This method accepts any of the following day symbols:
26
- # :monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday
26
+ # +:monday+, +:tuesday+, +:wednesday+, +:thursday+, +:friday+, +:saturday+, +:sunday+
27
27
  def beginning_of_week=(week_start)
28
- Thread.current[:beginning_of_week] = find_beginning_of_week!(week_start)
28
+ ::ActiveSupport::IsolatedExecutionState[:beginning_of_week] = find_beginning_of_week!(week_start)
29
29
  end
30
30
 
31
- # Returns week start day symbol (e.g. :monday), or raises an +ArgumentError+ for invalid day symbol.
31
+ # Returns week start day symbol (e.g. +:monday+), or raises an +ArgumentError+ for invalid day symbol.
32
32
  def find_beginning_of_week!(week_start)
33
33
  raise ArgumentError, "Invalid beginning of week: #{week_start}" unless ::Date::DAYS_INTO_WEEK.key?(week_start)
34
34
  week_start
@@ -87,7 +87,7 @@ class Date
87
87
  end
88
88
  alias :at_end_of_day :end_of_day
89
89
 
90
- def plus_with_duration(other) #:nodoc:
90
+ def plus_with_duration(other) # :nodoc:
91
91
  if ActiveSupport::Duration === other
92
92
  other.since(self)
93
93
  else
@@ -97,7 +97,7 @@ class Date
97
97
  alias_method :plus_without_duration, :+
98
98
  alias_method :+, :plus_with_duration
99
99
 
100
- def minus_with_duration(other) #:nodoc:
100
+ def minus_with_duration(other) # :nodoc:
101
101
  if ActiveSupport::Duration === other
102
102
  plus_with_duration(-other)
103
103
  else
@@ -109,6 +109,21 @@ class Date
109
109
 
110
110
  # Provides precise Date calculations for years, months, and days. The +options+ parameter takes a hash with
111
111
  # any of these keys: <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>.
112
+ #
113
+ # The increments are applied in order of time units from largest to smallest.
114
+ # In other words, the date is incremented first by +:years+, then by
115
+ # +:months+, then by +:weeks+, then by +:days+. This order can affect the
116
+ # result around the end of a month. For example, incrementing first by months
117
+ # then by days:
118
+ #
119
+ # Date.new(2004, 9, 30).advance(months: 1, days: 1)
120
+ # # => Sun, 31 Oct 2004
121
+ #
122
+ # Whereas incrementing first by days then by months yields a different result:
123
+ #
124
+ # Date.new(2004, 9, 30).advance(days: 1).advance(months: 1)
125
+ # # => Mon, 01 Nov 2004
126
+ #
112
127
  def advance(options)
113
128
  d = self
114
129
 
@@ -22,21 +22,21 @@ class Date
22
22
 
23
23
  # Convert to a formatted string. See DATE_FORMATS for predefined formats.
24
24
  #
25
- # This method is aliased to <tt>to_s</tt>.
25
+ # This method is aliased to <tt>to_formatted_s</tt>.
26
26
  #
27
27
  # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
28
28
  #
29
+ # date.to_fs(:db) # => "2007-11-10"
29
30
  # date.to_formatted_s(:db) # => "2007-11-10"
30
- # date.to_s(:db) # => "2007-11-10"
31
31
  #
32
- # date.to_formatted_s(:short) # => "10 Nov"
33
- # date.to_formatted_s(:number) # => "20071110"
34
- # date.to_formatted_s(:long) # => "November 10, 2007"
35
- # date.to_formatted_s(:long_ordinal) # => "November 10th, 2007"
36
- # date.to_formatted_s(:rfc822) # => "10 Nov 2007"
37
- # date.to_formatted_s(:iso8601) # => "2007-11-10"
32
+ # date.to_fs(:short) # => "10 Nov"
33
+ # date.to_fs(:number) # => "20071110"
34
+ # date.to_fs(:long) # => "November 10, 2007"
35
+ # date.to_fs(:long_ordinal) # => "November 10th, 2007"
36
+ # date.to_fs(:rfc822) # => "10 Nov 2007"
37
+ # date.to_fs(:iso8601) # => "2007-11-10"
38
38
  #
39
- # == Adding your own date formats to to_formatted_s
39
+ # == Adding your own date formats to to_fs
40
40
  # You can add your own formats to the Date::DATE_FORMATS hash.
41
41
  # Use the format name as the hash key and either a strftime string
42
42
  # or Proc instance that takes a date argument as the value.
@@ -44,7 +44,7 @@ class Date
44
44
  # # config/initializers/date_formats.rb
45
45
  # Date::DATE_FORMATS[:month_and_year] = '%B %Y'
46
46
  # Date::DATE_FORMATS[:short_ordinal] = ->(date) { date.strftime("%B #{date.day.ordinalize}") }
47
- def to_formatted_s(format = :default)
47
+ def to_fs(format = :default)
48
48
  if formatter = DATE_FORMATS[format]
49
49
  if formatter.respond_to?(:call)
50
50
  formatter.call(self).to_s
@@ -55,8 +55,8 @@ class Date
55
55
  to_default_s
56
56
  end
57
57
  end
58
+ alias_method :to_formatted_s, :to_fs
58
59
  alias_method :to_default_s, :to_s
59
- alias_method :to_s, :to_formatted_s
60
60
 
61
61
  # Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005"
62
62
  def readable_inspect
@@ -68,7 +68,7 @@ class Date
68
68
  silence_redefinition_of_method :to_time
69
69
 
70
70
  # Converts a Date instance to a Time, where the time is set to the beginning of the day.
71
- # The timezone can be either :local or :utc (default :local).
71
+ # The timezone can be either +:local+ or +:utc+ (default +:local+).
72
72
  #
73
73
  # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
74
74
  #
@@ -77,8 +77,8 @@ class Date
77
77
  #
78
78
  # date.to_time(:utc) # => 2007-11-10 00:00:00 UTC
79
79
  #
80
- # NOTE: The :local timezone is Ruby's *process* timezone, i.e. ENV['TZ'].
81
- # If the *application's* timezone is needed, then use +in_time_zone+ instead.
80
+ # NOTE: The +:local+ timezone is Ruby's *process* timezone, i.e. <tt>ENV['TZ']</tt>.
81
+ # If the <b>application's</b> timezone is needed, then use +in_time_zone+ instead.
82
82
  def to_time(form = :local)
83
83
  raise ArgumentError, "Expected :local or :utc, got #{form.inspect}." unless [:local, :utc].include?(form)
84
84
  ::Time.public_send(form, year, month, day)
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+
5
+ class Date
6
+ NOT_SET = Object.new # :nodoc:
7
+ def to_s(format = NOT_SET) # :nodoc:
8
+ if formatter = DATE_FORMATS[format]
9
+ ActiveSupport::Deprecation.warn(
10
+ "Date#to_s(#{format.inspect}) is deprecated. Please use Date#to_fs(#{format.inspect}) instead."
11
+ )
12
+ if formatter.respond_to?(:call)
13
+ formatter.call(self).to_s
14
+ else
15
+ strftime(formatter)
16
+ end
17
+ elsif format == NOT_SET
18
+ if formatter = DATE_FORMATS[:default]
19
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
20
+ Using a :default format for Date#to_s is deprecated. Please use Date#to_fs instead. If you fixed all places
21
+ inside your application that you see this deprecation, you can set
22
+ `ENV['RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION']` to `"true"` in the `config/application.rb` file before
23
+ the `Bundler.require` call to fix all the callers outside of your application.
24
+ MSG
25
+ if formatter.respond_to?(:call)
26
+ formatter.call(self).to_s
27
+ else
28
+ strftime(formatter)
29
+ end
30
+ else
31
+ to_default_s
32
+ end
33
+ else
34
+ ActiveSupport::Deprecation.warn(
35
+ "Date#to_s(#{format.inspect}) is deprecated. Please use Date#to_fs(#{format.inspect}) instead."
36
+ )
37
+ to_default_s
38
+ end
39
+ end
40
+ end
@@ -4,4 +4,5 @@ require "active_support/core_ext/date/acts_like"
4
4
  require "active_support/core_ext/date/blank"
5
5
  require "active_support/core_ext/date/calculations"
6
6
  require "active_support/core_ext/date/conversions"
7
+ require "active_support/core_ext/date/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"]
7
8
  require "active_support/core_ext/date/zones"
@@ -201,7 +201,7 @@ module DateAndTime
201
201
  end
202
202
  end
203
203
 
204
- # Short-hand for months_since(3)
204
+ # Short-hand for <tt>months_since(3)</tt>.
205
205
  def next_quarter
206
206
  months_since(3)
207
207
  end
@@ -226,18 +226,18 @@ module DateAndTime
226
226
  end
227
227
  alias_method :last_weekday, :prev_weekday
228
228
 
229
- # Short-hand for months_ago(1).
229
+ # Short-hand for <tt>months_ago(1)</tt>.
230
230
  def last_month
231
231
  months_ago(1)
232
232
  end
233
233
 
234
- # Short-hand for months_ago(3).
234
+ # Short-hand for <tt>months_ago(3)</tt>.
235
235
  def prev_quarter
236
236
  months_ago(3)
237
237
  end
238
238
  alias_method :last_quarter, :prev_quarter
239
239
 
240
- # Short-hand for years_ago(1).
240
+ # Short-hand for <tt>years_ago(1)</tt>.
241
241
  def last_year
242
242
  years_ago(1)
243
243
  end
@@ -15,7 +15,7 @@ module DateAndTime
15
15
 
16
16
  # Change the output of <tt>ActiveSupport::TimeZone.utc_to_local</tt>.
17
17
  #
18
- # When `true`, it returns local times with an UTC offset, with `false` local
18
+ # When +true+, it returns local times with a UTC offset, with +false+ local
19
19
  # times are returned as UTC.
20
20
  #
21
21
  # # Given this zone:
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "date"
4
4
 
5
- class DateTime #:nodoc:
5
+ class DateTime # :nodoc:
6
6
  # No DateTime is ever blank:
7
7
  #
8
8
  # DateTime.now.blank? # => false
@@ -75,6 +75,10 @@ class DateTime
75
75
  # The +options+ parameter takes a hash with any of these keys: <tt>:years</tt>,
76
76
  # <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>,
77
77
  # <tt>:minutes</tt>, <tt>:seconds</tt>.
78
+ #
79
+ # Just like Date#advance, increments are applied in order of time units from
80
+ # largest to smallest. This order can affect the result around the end of a
81
+ # month.
78
82
  def advance(options)
79
83
  unless options[:weeks].nil?
80
84
  options[:weeks], partial_weeks = options[:weeks].divmod(1)
@@ -9,21 +9,21 @@ require "active_support/values/time_zone"
9
9
  class DateTime
10
10
  # Convert to a formatted string. See Time::DATE_FORMATS for predefined formats.
11
11
  #
12
- # This method is aliased to <tt>to_s</tt>.
12
+ # This method is aliased to <tt>to_formatted_s</tt>.
13
13
  #
14
14
  # === Examples
15
15
  # datetime = DateTime.civil(2007, 12, 4, 0, 0, 0, 0) # => Tue, 04 Dec 2007 00:00:00 +0000
16
16
  #
17
- # datetime.to_formatted_s(:db) # => "2007-12-04 00:00:00"
18
- # datetime.to_s(:db) # => "2007-12-04 00:00:00"
19
- # datetime.to_s(:number) # => "20071204000000"
20
- # datetime.to_formatted_s(:short) # => "04 Dec 00:00"
21
- # datetime.to_formatted_s(:long) # => "December 04, 2007 00:00"
22
- # datetime.to_formatted_s(:long_ordinal) # => "December 4th, 2007 00:00"
23
- # datetime.to_formatted_s(:rfc822) # => "Tue, 04 Dec 2007 00:00:00 +0000"
24
- # datetime.to_formatted_s(:iso8601) # => "2007-12-04T00:00:00+00:00"
17
+ # datetime.to_fs(:db) # => "2007-12-04 00:00:00"
18
+ # datetime.to_formatted_s(:db) # => "2007-12-04 00:00:00"
19
+ # datetime.to_fs(:number) # => "20071204000000"
20
+ # datetime.to_fs(:short) # => "04 Dec 00:00"
21
+ # datetime.to_fs(:long) # => "December 04, 2007 00:00"
22
+ # datetime.to_fs(:long_ordinal) # => "December 4th, 2007 00:00"
23
+ # datetime.to_fs(:rfc822) # => "Tue, 04 Dec 2007 00:00:00 +0000"
24
+ # datetime.to_fs(:iso8601) # => "2007-12-04T00:00:00+00:00"
25
25
  #
26
- # == Adding your own datetime formats to to_formatted_s
26
+ # == Adding your own datetime formats to to_fs
27
27
  # DateTime formats are shared with Time. You can add your own to the
28
28
  # Time::DATE_FORMATS hash. Use the format name as the hash key and
29
29
  # either a strftime string or Proc instance that takes a time or
@@ -32,15 +32,15 @@ class DateTime
32
32
  # # config/initializers/time_formats.rb
33
33
  # Time::DATE_FORMATS[:month_and_year] = '%B %Y'
34
34
  # Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
35
- def to_formatted_s(format = :default)
35
+ def to_fs(format = :default)
36
36
  if formatter = ::Time::DATE_FORMATS[format]
37
37
  formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
38
38
  else
39
39
  to_default_s
40
40
  end
41
41
  end
42
+ alias_method :to_formatted_s, :to_fs
42
43
  alias_method :to_default_s, :to_s if instance_methods(false).include?(:to_s)
43
- alias_method :to_s, :to_formatted_s
44
44
 
45
45
  # Returns a formatted string of the offset from UTC, or an alternative
46
46
  # string if the time zone is already UTC.
@@ -54,7 +54,7 @@ class DateTime
54
54
 
55
55
  # Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005 14:30:00 +0000".
56
56
  def readable_inspect
57
- to_s(:rfc822)
57
+ to_fs(:rfc822)
58
58
  end
59
59
  alias_method :default_inspect, :inspect
60
60
  alias_method :inspect, :readable_inspect
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+
5
+ class DateTime
6
+ NOT_SET = Object.new # :nodoc:
7
+ def to_s(format = NOT_SET) # :nodoc:
8
+ if formatter = ::Time::DATE_FORMATS[format]
9
+ ActiveSupport::Deprecation.warn(
10
+ "DateTime#to_s(#{format.inspect}) is deprecated. Please use DateTime#to_fs(#{format.inspect}) instead."
11
+ )
12
+ formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
13
+ elsif format == NOT_SET
14
+ if formatter = ::Time::DATE_FORMATS[:default]
15
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
16
+ Using a :default format for DateTime#to_s is deprecated. Please use DateTime#to_fs instead. If you fixed all
17
+ places inside your application that you see this deprecation, you can set
18
+ `ENV['RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION']` to `"true"` in the `config/application.rb` file before
19
+ the `Bundler.require` call to fix all the callers outside of your application.
20
+ MSG
21
+ if formatter.respond_to?(:call)
22
+ formatter.call(self).to_s
23
+ else
24
+ strftime(formatter)
25
+ end
26
+ else
27
+ to_default_s
28
+ end
29
+ else
30
+ ActiveSupport::Deprecation.warn(
31
+ "DateTime#to_s(#{format.inspect}) is deprecated. Please use DateTime#to_fs(#{format.inspect}) instead."
32
+ )
33
+ to_default_s
34
+ end
35
+ end
36
+ end
@@ -5,3 +5,4 @@ require "active_support/core_ext/date_time/blank"
5
5
  require "active_support/core_ext/date_time/calculations"
6
6
  require "active_support/core_ext/date_time/compatibility"
7
7
  require "active_support/core_ext/date_time/conversions"
8
+ require "active_support/core_ext/date_time/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"]
@@ -1,29 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "securerandom"
4
+ require "openssl"
4
5
 
5
6
  module Digest
6
7
  module UUID
7
- DNS_NAMESPACE = "k\xA7\xB8\x10\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
8
- URL_NAMESPACE = "k\xA7\xB8\x11\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
9
- OID_NAMESPACE = "k\xA7\xB8\x12\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
10
- X500_NAMESPACE = "k\xA7\xB8\x14\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
8
+ DNS_NAMESPACE = "k\xA7\xB8\x10\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" # :nodoc:
9
+ URL_NAMESPACE = "k\xA7\xB8\x11\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" # :nodoc:
10
+ OID_NAMESPACE = "k\xA7\xB8\x12\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" # :nodoc:
11
+ X500_NAMESPACE = "k\xA7\xB8\x14\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" # :nodoc:
12
+
13
+ mattr_accessor :use_rfc4122_namespaced_uuids, instance_accessor: false, default: false
11
14
 
12
15
  # Generates a v5 non-random UUID (Universally Unique IDentifier).
13
16
  #
14
- # Using Digest::MD5 generates version 3 UUIDs; Digest::SHA1 generates version 5 UUIDs.
17
+ # Using OpenSSL::Digest::MD5 generates version 3 UUIDs; OpenSSL::Digest::SHA1 generates version 5 UUIDs.
15
18
  # uuid_from_hash always generates the same UUID for a given name and namespace combination.
16
19
  #
17
20
  # See RFC 4122 for details of UUID at: https://www.ietf.org/rfc/rfc4122.txt
18
- def self.uuid_from_hash(hash_class, uuid_namespace, name)
19
- if hash_class == Digest::MD5
21
+ def self.uuid_from_hash(hash_class, namespace, name)
22
+ if hash_class == Digest::MD5 || hash_class == OpenSSL::Digest::MD5
20
23
  version = 3
21
- elsif hash_class == Digest::SHA1
24
+ elsif hash_class == Digest::SHA1 || hash_class == OpenSSL::Digest::SHA1
22
25
  version = 5
23
26
  else
24
- raise ArgumentError, "Expected Digest::SHA1 or Digest::MD5, got #{hash_class.name}."
27
+ raise ArgumentError, "Expected OpenSSL::Digest::SHA1 or OpenSSL::Digest::MD5, got #{hash_class.name}."
25
28
  end
26
29
 
30
+ uuid_namespace = pack_uuid_namespace(namespace)
31
+
27
32
  hash = hash_class.new
28
33
  hash.update(uuid_namespace)
29
34
  hash.update(name)
@@ -35,19 +40,40 @@ module Digest
35
40
  "%08x-%04x-%04x-%04x-%04x%08x" % ary
36
41
  end
37
42
 
38
- # Convenience method for uuid_from_hash using Digest::MD5.
43
+ # Convenience method for uuid_from_hash using OpenSSL::Digest::MD5.
39
44
  def self.uuid_v3(uuid_namespace, name)
40
- uuid_from_hash(Digest::MD5, uuid_namespace, name)
45
+ uuid_from_hash(OpenSSL::Digest::MD5, uuid_namespace, name)
41
46
  end
42
47
 
43
- # Convenience method for uuid_from_hash using Digest::SHA1.
48
+ # Convenience method for uuid_from_hash using OpenSSL::Digest::SHA1.
44
49
  def self.uuid_v5(uuid_namespace, name)
45
- uuid_from_hash(Digest::SHA1, uuid_namespace, name)
50
+ uuid_from_hash(OpenSSL::Digest::SHA1, uuid_namespace, name)
46
51
  end
47
52
 
48
53
  # Convenience method for SecureRandom.uuid.
49
54
  def self.uuid_v4
50
55
  SecureRandom.uuid
51
56
  end
57
+
58
+ def self.pack_uuid_namespace(namespace)
59
+ if [DNS_NAMESPACE, OID_NAMESPACE, URL_NAMESPACE, X500_NAMESPACE].include?(namespace)
60
+ namespace
61
+ elsif use_rfc4122_namespaced_uuids == true
62
+ match_data = namespace.match(/\A(\h{8})-(\h{4})-(\h{4})-(\h{4})-(\h{4})(\h{8})\z/)
63
+
64
+ raise ArgumentError, "Only UUIDs are valid namespace identifiers" unless match_data.present?
65
+
66
+ match_data.captures.map { |s| s.to_i(16) }.pack("NnnnnN")
67
+ else
68
+ ActiveSupport::Deprecation.warn <<~WARNING.squish
69
+ Providing a namespace ID that is not one of the constants defined on Digest::UUID generates an incorrect UUID value according to RFC 4122.
70
+ To enable the correct behavior, set the Rails.application.config.active_support.use_rfc4122_namespaced_uuids configuration option to true.
71
+ WARNING
72
+
73
+ namespace
74
+ end
75
+ end
76
+
77
+ private_class_method :pack_uuid_namespace
52
78
  end
53
79
  end