activesupport 5.2.4.3 → 7.0.3

Sign up to get free protection for your applications and to get access to all the features.

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,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/kernel/singleton_class"
4
3
  require "active_support/core_ext/module/redefine_method"
5
- require "active_support/core_ext/array/extract_options"
6
4
 
7
5
  class Class
8
6
  # Declare a class-level attribute whose value is inheritable by subclasses.
@@ -84,63 +82,50 @@ class Class
84
82
  # To set a default value for the attribute, pass <tt>default:</tt>, like so:
85
83
  #
86
84
  # class_attribute :settings, default: {}
87
- def class_attribute(*attrs)
88
- options = attrs.extract_options!
89
- instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true)
90
- instance_writer = options.fetch(:instance_accessor, true) && options.fetch(:instance_writer, true)
91
- instance_predicate = options.fetch(:instance_predicate, true)
92
- default_value = options.fetch(:default, nil)
85
+ def class_attribute(*attrs, instance_accessor: true,
86
+ instance_reader: instance_accessor, instance_writer: instance_accessor, instance_predicate: true, default: nil)
93
87
 
88
+ class_methods, methods = [], []
94
89
  attrs.each do |name|
95
- singleton_class.silence_redefinition_of_method(name)
96
- define_singleton_method(name) { nil }
97
-
98
- singleton_class.silence_redefinition_of_method("#{name}?")
99
- define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate
100
-
101
- ivar = "@#{name}"
90
+ unless name.is_a?(Symbol) || name.is_a?(String)
91
+ raise TypeError, "#{name.inspect} is not a symbol nor a string"
92
+ end
102
93
 
103
- singleton_class.silence_redefinition_of_method("#{name}=")
104
- define_singleton_method("#{name}=") do |val|
105
- singleton_class.class_eval do
106
- redefine_method(name) { val }
94
+ class_methods << <<~RUBY # In case the method exists and is not public
95
+ silence_redefinition_of_method def #{name}
107
96
  end
97
+ RUBY
108
98
 
109
- if singleton_class?
110
- class_eval do
111
- redefine_method(name) do
112
- if instance_variable_defined? ivar
113
- instance_variable_get ivar
114
- else
115
- singleton_class.send name
116
- end
117
- end
118
- end
99
+ methods << <<~RUBY if instance_reader
100
+ silence_redefinition_of_method def #{name}
101
+ defined?(@#{name}) ? @#{name} : self.class.#{name}
119
102
  end
120
- val
121
- end
103
+ RUBY
122
104
 
123
- if instance_reader
124
- redefine_method(name) do
125
- if instance_variable_defined?(ivar)
126
- instance_variable_get ivar
127
- else
128
- self.class.public_send name
129
- end
105
+ class_methods << <<~RUBY
106
+ silence_redefinition_of_method def #{name}=(value)
107
+ redefine_method(:#{name}) { value } if singleton_class?
108
+ redefine_singleton_method(:#{name}) { value }
109
+ value
130
110
  end
111
+ RUBY
131
112
 
132
- redefine_method("#{name}?") { !!public_send(name) } if instance_predicate
133
- end
113
+ methods << <<~RUBY if instance_writer
114
+ silence_redefinition_of_method(:#{name}=)
115
+ attr_writer :#{name}
116
+ RUBY
134
117
 
135
- if instance_writer
136
- redefine_method("#{name}=") do |val|
137
- instance_variable_set ivar, val
118
+ if instance_predicate
119
+ class_methods << "silence_redefinition_of_method def #{name}?; !!self.#{name}; end"
120
+ if instance_reader
121
+ methods << "silence_redefinition_of_method def #{name}?; !!self.#{name}; end"
138
122
  end
139
123
  end
140
-
141
- unless default_value.nil?
142
- self.send("#{name}=", default_value)
143
- end
144
124
  end
125
+
126
+ location = caller_locations(1, 1).first
127
+ class_eval(["class << self", *class_methods, "end", *methods].join(";").tr("\n", ";"), location.path, location.lineno)
128
+
129
+ attrs.each { |name| public_send("#{name}=", default) }
145
130
  end
146
131
  end
@@ -1,10 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Class
4
- begin
5
- # Test if this Ruby supports each_object against singleton_class
6
- ObjectSpace.each_object(Numeric.singleton_class) {}
3
+ require "active_support/ruby_features"
7
4
 
5
+ class Class
6
+ if ActiveSupport::RubyFeatures::CLASS_SUBCLASSES
8
7
  # Returns an array with all classes that are < than its receiver.
9
8
  #
10
9
  # class C; end
@@ -19,21 +18,13 @@ class Class
19
18
  # class D < C; end
20
19
  # C.descendants # => [B, A, D]
21
20
  def descendants
22
- descendants = []
23
- ObjectSpace.each_object(singleton_class) do |k|
24
- next if k.singleton_class?
25
- descendants.unshift k unless k == self
26
- end
27
- descendants
21
+ subclasses.concat(subclasses.flat_map(&:descendants))
28
22
  end
29
- rescue StandardError # JRuby 9.0.4.0 and earlier
23
+ else
30
24
  def descendants
31
- descendants = []
32
- ObjectSpace.each_object(Class) do |k|
33
- descendants.unshift k if k < self
25
+ ObjectSpace.each_object(singleton_class).reject do |k|
26
+ k.singleton_class? || k == self
34
27
  end
35
- descendants.uniq!
36
- descendants
37
28
  end
38
29
  end
39
30
 
@@ -45,10 +36,6 @@ class Class
45
36
  #
46
37
  # Foo.subclasses # => [Bar]
47
38
  def subclasses
48
- subclasses, chain = [], descendants
49
- chain.each do |k|
50
- subclasses << k unless chain.any? { |c| c > k }
51
- end
52
- subclasses
53
- end
39
+ descendants.select { |descendant| descendant.superclass == self }
40
+ end unless ActiveSupport::RubyFeatures::CLASS_SUBCLASSES
54
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
@@ -110,12 +110,13 @@ class Date
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
112
  def advance(options)
113
- options = options.dup
114
113
  d = self
115
- d = d >> options.delete(:years) * 12 if options[:years]
116
- d = d >> options.delete(:months) if options[:months]
117
- d = d + options.delete(:weeks) * 7 if options[:weeks]
118
- d = d + options.delete(:days) if options[:days]
114
+
115
+ d = d >> options[:years] * 12 if options[:years]
116
+ d = d >> options[:months] if options[:months]
117
+ d = d + options[:weeks] * 7 if options[:weeks]
118
+ d = d + options[:days] if options[:days]
119
+
119
120
  d
120
121
  end
121
122
 
@@ -10,6 +10,7 @@ class Date
10
10
  short: "%d %b",
11
11
  long: "%B %d, %Y",
12
12
  db: "%Y-%m-%d",
13
+ inspect: "%Y-%m-%d",
13
14
  number: "%Y%m%d",
14
15
  long_ordinal: lambda { |date|
15
16
  day_format = ActiveSupport::Inflector.ordinalize(date.day)
@@ -21,21 +22,21 @@ class Date
21
22
 
22
23
  # Convert to a formatted string. See DATE_FORMATS for predefined formats.
23
24
  #
24
- # This method is aliased to <tt>to_s</tt>.
25
+ # This method is aliased to <tt>to_formatted_s</tt>.
25
26
  #
26
27
  # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
27
28
  #
29
+ # date.to_fs(:db) # => "2007-11-10"
28
30
  # date.to_formatted_s(:db) # => "2007-11-10"
29
- # date.to_s(:db) # => "2007-11-10"
30
31
  #
31
- # date.to_formatted_s(:short) # => "10 Nov"
32
- # date.to_formatted_s(:number) # => "20071110"
33
- # date.to_formatted_s(:long) # => "November 10, 2007"
34
- # date.to_formatted_s(:long_ordinal) # => "November 10th, 2007"
35
- # date.to_formatted_s(:rfc822) # => "10 Nov 2007"
36
- # 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"
37
38
  #
38
- # == Adding your own date formats to to_formatted_s
39
+ # == Adding your own date formats to to_fs
39
40
  # You can add your own formats to the Date::DATE_FORMATS hash.
40
41
  # Use the format name as the hash key and either a strftime string
41
42
  # or Proc instance that takes a date argument as the value.
@@ -43,7 +44,7 @@ class Date
43
44
  # # config/initializers/date_formats.rb
44
45
  # Date::DATE_FORMATS[:month_and_year] = '%B %Y'
45
46
  # Date::DATE_FORMATS[:short_ordinal] = ->(date) { date.strftime("%B #{date.day.ordinalize}") }
46
- def to_formatted_s(format = :default)
47
+ def to_fs(format = :default)
47
48
  if formatter = DATE_FORMATS[format]
48
49
  if formatter.respond_to?(:call)
49
50
  formatter.call(self).to_s
@@ -54,8 +55,8 @@ class Date
54
55
  to_default_s
55
56
  end
56
57
  end
58
+ alias_method :to_formatted_s, :to_fs
57
59
  alias_method :to_default_s, :to_s
58
- alias_method :to_s, :to_formatted_s
59
60
 
60
61
  # Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005"
61
62
  def readable_inspect
@@ -67,7 +68,7 @@ class Date
67
68
  silence_redefinition_of_method :to_time
68
69
 
69
70
  # Converts a Date instance to a Time, where the time is set to the beginning of the day.
70
- # The timezone can be either :local or :utc (default :local).
71
+ # The timezone can be either +:local+ or +:utc+ (default +:local+).
71
72
  #
72
73
  # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
73
74
  #
@@ -76,11 +77,11 @@ class Date
76
77
  #
77
78
  # date.to_time(:utc) # => 2007-11-10 00:00:00 UTC
78
79
  #
79
- # NOTE: The :local timezone is Ruby's *process* timezone, i.e. ENV['TZ'].
80
- # 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.
81
82
  def to_time(form = :local)
82
83
  raise ArgumentError, "Expected :local or :utc, got #{form.inspect}." unless [:local, :utc].include?(form)
83
- ::Time.send(form, year, month, day)
84
+ ::Time.public_send(form, year, month, day)
84
85
  end
85
86
 
86
87
  silence_redefinition_of_method :xmlschema
@@ -0,0 +1,26 @@
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
+ to_default_s
19
+ else
20
+ ActiveSupport::Deprecation.warn(
21
+ "Date#to_s(#{format.inspect}) is deprecated. Please use Date#to_fs(#{format.inspect}) instead."
22
+ )
23
+ to_default_s
24
+ end
25
+ end
26
+ 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"
@@ -1,17 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/object/try"
4
+ require "active_support/core_ext/date_time/conversions"
4
5
 
5
6
  module DateAndTime
6
7
  module Calculations
7
8
  DAYS_INTO_WEEK = {
8
- monday: 0,
9
- tuesday: 1,
10
- wednesday: 2,
11
- thursday: 3,
12
- friday: 4,
13
- saturday: 5,
14
- sunday: 6
9
+ sunday: 0,
10
+ monday: 1,
11
+ tuesday: 2,
12
+ wednesday: 3,
13
+ thursday: 4,
14
+ friday: 5,
15
+ saturday: 6
15
16
  }
16
17
  WEEKEND_DAYS = [ 6, 0 ]
17
18
 
@@ -20,26 +21,28 @@ module DateAndTime
20
21
  advance(days: -1)
21
22
  end
22
23
 
23
- # Returns a new date/time the specified number of days ago.
24
- def prev_day(days = 1)
25
- advance(days: -days)
26
- end
27
-
28
24
  # Returns a new date/time representing tomorrow.
29
25
  def tomorrow
30
26
  advance(days: 1)
31
27
  end
32
28
 
33
- # Returns a new date/time the specified number of days in the future.
34
- def next_day(days = 1)
35
- advance(days: days)
36
- end
37
-
38
29
  # Returns true if the date/time is today.
39
30
  def today?
40
31
  to_date == ::Date.current
41
32
  end
42
33
 
34
+ # Returns true if the date/time is tomorrow.
35
+ def tomorrow?
36
+ to_date == ::Date.current.tomorrow
37
+ end
38
+ alias :next_day? :tomorrow?
39
+
40
+ # Returns true if the date/time is yesterday.
41
+ def yesterday?
42
+ to_date == ::Date.current.yesterday
43
+ end
44
+ alias :prev_day? :yesterday?
45
+
43
46
  # Returns true if the date/time is in the past.
44
47
  def past?
45
48
  self < self.class.current
@@ -60,6 +63,16 @@ module DateAndTime
60
63
  !WEEKEND_DAYS.include?(wday)
61
64
  end
62
65
 
66
+ # Returns true if the date/time falls before <tt>date_or_time</tt>.
67
+ def before?(date_or_time)
68
+ self < date_or_time
69
+ end
70
+
71
+ # Returns true if the date/time falls after <tt>date_or_time</tt>.
72
+ def after?(date_or_time)
73
+ self > date_or_time
74
+ end
75
+
63
76
  # Returns a new date/time the specified number of days ago.
64
77
  def days_ago(days)
65
78
  advance(days: -days)
@@ -124,7 +137,7 @@ module DateAndTime
124
137
  # now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
125
138
  # now.beginning_of_quarter # => Wed, 01 Jul 2015 00:00:00 +0000
126
139
  def beginning_of_quarter
127
- first_quarter_month = [10, 7, 4, 1].detect { |m| m <= month }
140
+ first_quarter_month = month - (2 + month) % 3
128
141
  beginning_of_month.change(month: first_quarter_month)
129
142
  end
130
143
  alias :at_beginning_of_quarter :beginning_of_quarter
@@ -139,7 +152,7 @@ module DateAndTime
139
152
  # now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
140
153
  # now.end_of_quarter # => Wed, 30 Sep 2015 23:59:59 +0000
141
154
  def end_of_quarter
142
- last_quarter_month = [3, 6, 9, 12].detect { |m| m >= month }
155
+ last_quarter_month = month + (12 - month) % 3
143
156
  beginning_of_month.change(month: last_quarter_month).end_of_month
144
157
  end
145
158
  alias :at_end_of_quarter :end_of_quarter
@@ -188,21 +201,11 @@ module DateAndTime
188
201
  end
189
202
  end
190
203
 
191
- # Returns a new date/time the specified number of months in the future.
192
- def next_month(months = 1)
193
- advance(months: months)
194
- end
195
-
196
- # Short-hand for months_since(3)
204
+ # Short-hand for <tt>months_since(3)</tt>.
197
205
  def next_quarter
198
206
  months_since(3)
199
207
  end
200
208
 
201
- # Returns a new date/time the specified number of years in the future.
202
- def next_year(years = 1)
203
- advance(years: years)
204
- end
205
-
206
209
  # Returns a new date/time representing the given day in the previous week.
207
210
  # Week is assumed to start on +start_day+, default is
208
211
  # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
@@ -223,28 +226,18 @@ module DateAndTime
223
226
  end
224
227
  alias_method :last_weekday, :prev_weekday
225
228
 
226
- # Returns a new date/time the specified number of months ago.
227
- def prev_month(months = 1)
228
- advance(months: -months)
229
- end
230
-
231
- # Short-hand for months_ago(1).
229
+ # Short-hand for <tt>months_ago(1)</tt>.
232
230
  def last_month
233
231
  months_ago(1)
234
232
  end
235
233
 
236
- # Short-hand for months_ago(3).
234
+ # Short-hand for <tt>months_ago(3)</tt>.
237
235
  def prev_quarter
238
236
  months_ago(3)
239
237
  end
240
238
  alias_method :last_quarter, :prev_quarter
241
239
 
242
- # Returns a new date/time the specified number of years ago.
243
- def prev_year(years = 1)
244
- advance(years: -years)
245
- end
246
-
247
- # Short-hand for years_ago(1).
240
+ # Short-hand for <tt>years_ago(1)</tt>.
248
241
  def last_year
249
242
  years_ago(1)
250
243
  end
@@ -253,9 +246,8 @@ module DateAndTime
253
246
  # Week is assumed to start on +start_day+, default is
254
247
  # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
255
248
  def days_to_week_start(start_day = Date.beginning_of_week)
256
- start_day_number = DAYS_INTO_WEEK[start_day]
257
- current_day_number = wday != 0 ? wday - 1 : 6
258
- (current_day_number - start_day_number) % 7
249
+ start_day_number = DAYS_INTO_WEEK.fetch(start_day)
250
+ (wday - start_day_number) % 7
259
251
  end
260
252
 
261
253
  # Returns a new date/time representing the start of this week on the given day.
@@ -336,8 +328,7 @@ module DateAndTime
336
328
  # today.next_occurring(:monday) # => Mon, 18 Dec 2017
337
329
  # today.next_occurring(:thursday) # => Thu, 21 Dec 2017
338
330
  def next_occurring(day_of_week)
339
- current_day_number = wday != 0 ? wday - 1 : 6
340
- from_now = DAYS_INTO_WEEK.fetch(day_of_week) - current_day_number
331
+ from_now = DAYS_INTO_WEEK.fetch(day_of_week) - wday
341
332
  from_now += 7 unless from_now > 0
342
333
  advance(days: from_now)
343
334
  end
@@ -348,8 +339,7 @@ module DateAndTime
348
339
  # today.prev_occurring(:monday) # => Mon, 11 Dec 2017
349
340
  # today.prev_occurring(:thursday) # => Thu, 07 Dec 2017
350
341
  def prev_occurring(day_of_week)
351
- current_day_number = wday != 0 ? wday - 1 : 6
352
- ago = current_day_number - DAYS_INTO_WEEK.fetch(day_of_week)
342
+ ago = wday - DAYS_INTO_WEEK.fetch(day_of_week)
353
343
  ago += 7 unless ago > 0
354
344
  advance(days: -ago)
355
345
  end
@@ -364,7 +354,7 @@ module DateAndTime
364
354
  end
365
355
 
366
356
  def days_span(day)
367
- (DAYS_INTO_WEEK[day] - DAYS_INTO_WEEK[Date.beginning_of_week]) % 7
357
+ (DAYS_INTO_WEEK.fetch(day) - DAYS_INTO_WEEK.fetch(Date.beginning_of_week)) % 7
368
358
  end
369
359
 
370
360
  def copy_time_to(other)
@@ -12,5 +12,20 @@ module DateAndTime
12
12
  # this behavior, but new apps will have an initializer that sets
13
13
  # this to true, because the new behavior is preferred.
14
14
  mattr_accessor :preserve_timezone, instance_writer: false, default: false
15
+
16
+ # Change the output of <tt>ActiveSupport::TimeZone.utc_to_local</tt>.
17
+ #
18
+ # When +true+, it returns local times with a UTC offset, with +false+ local
19
+ # times are returned as UTC.
20
+ #
21
+ # # Given this zone:
22
+ # zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
23
+ #
24
+ # # With `utc_to_local_returns_utc_offset_times = false`, local time is converted to UTC:
25
+ # zone.utc_to_local(Time.utc(2000, 1)) # => 1999-12-31 19:00:00 UTC
26
+ #
27
+ # # With `utc_to_local_returns_utc_offset_times = true`, local time is returned with UTC offset:
28
+ # zone.utc_to_local(Time.utc(2000, 1)) # => 1999-12-31 19:00:00 -0500
29
+ mattr_accessor :utc_to_local_returns_utc_offset_times, instance_writer: false, default: false
15
30
  end
16
31
  end
@@ -29,7 +29,6 @@ module DateAndTime
29
29
  end
30
30
 
31
31
  private
32
-
33
32
  def time_with_zone(time, zone)
34
33
  if time
35
34
  ActiveSupport::TimeWithZone.new(time.utc? ? time : time.getutc, 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
@@ -110,7 +110,7 @@ class DateTime
110
110
  # instance time. Do not use this method in combination with x.months, use
111
111
  # months_since instead!
112
112
  def since(seconds)
113
- self + Rational(seconds.round, 86400)
113
+ self + Rational(seconds, 86400)
114
114
  end
115
115
  alias :in :since
116
116
 
@@ -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
@@ -96,7 +96,6 @@ class DateTime
96
96
  end
97
97
 
98
98
  private
99
-
100
99
  def offset_in_seconds
101
100
  (offset * 86400).to_i
102
101
  end