activesupport 4.2.5 → 4.2.11.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 (42) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +200 -0
  3. data/lib/active_support/cache/mem_cache_store.rb +1 -1
  4. data/lib/active_support/callbacks.rb +1 -1
  5. data/lib/active_support/core_ext/class/subclasses.rb +0 -2
  6. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  7. data/lib/active_support/core_ext/date_time/calculations.rb +22 -2
  8. data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
  9. data/lib/active_support/core_ext/date_time.rb +1 -0
  10. data/lib/active_support/core_ext/enumerable.rb +16 -0
  11. data/lib/active_support/core_ext/hash/compact.rb +19 -15
  12. data/lib/active_support/core_ext/hash/conversions.rb +1 -2
  13. data/lib/active_support/core_ext/hash/transform_values.rb +2 -2
  14. data/lib/active_support/core_ext/marshal.rb +8 -5
  15. data/lib/active_support/core_ext/module/delegation.rb +8 -0
  16. data/lib/active_support/core_ext/numeric/conversions.rb +9 -1
  17. data/lib/active_support/core_ext/object/duplicable.rb +58 -32
  18. data/lib/active_support/core_ext/string/access.rb +1 -1
  19. data/lib/active_support/core_ext/string/conversions.rb +1 -1
  20. data/lib/active_support/core_ext/time/calculations.rb +10 -1
  21. data/lib/active_support/core_ext/time/compatibility.rb +14 -0
  22. data/lib/active_support/core_ext/time.rb +1 -0
  23. data/lib/active_support/gem_version.rb +2 -2
  24. data/lib/active_support/hash_with_indifferent_access.rb +9 -0
  25. data/lib/active_support/inflector/methods.rb +1 -1
  26. data/lib/active_support/logger.rb +50 -0
  27. data/lib/active_support/logger_silence.rb +7 -4
  28. data/lib/active_support/logger_thread_safe_level.rb +32 -0
  29. data/lib/active_support/message_encryptor.rb +8 -1
  30. data/lib/active_support/per_thread_registry.rb +2 -0
  31. data/lib/active_support/security_utils.rb +7 -0
  32. data/lib/active_support/testing/time_helpers.rb +16 -13
  33. data/lib/active_support/time_with_zone.rb +28 -16
  34. data/lib/active_support/values/time_zone.rb +5 -3
  35. data/lib/active_support/xml_mini/libxml.rb +1 -3
  36. data/lib/active_support/xml_mini/libxmlsax.rb +1 -4
  37. data/lib/active_support/xml_mini/nokogiri.rb +1 -3
  38. data/lib/active_support/xml_mini/nokogirisax.rb +1 -3
  39. data/lib/active_support/xml_mini/rexml.rb +1 -3
  40. data/lib/active_support/xml_mini.rb +30 -15
  41. data/lib/active_support.rb +9 -0
  42. metadata +7 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 61b8d3f7b7567155481d04cb842d4ffafa441abe
4
- data.tar.gz: cadd0882bd760c4b0cb206a9abde82791e304413
2
+ SHA256:
3
+ metadata.gz: e5927887f8de9d6b13175ee528ab4606a7975d7b4eb27c7365c3ed5bbc620183
4
+ data.tar.gz: 1f4c3a900e5f84241a557376ecb5850a5c9c6b86be17f6929397871a9ae5f925
5
5
  SHA512:
6
- metadata.gz: 8b7f68146497c8b513710e3e5bee0782e6dc01039f78a910d1226ab9caf19b524feafa1df9dd859492f43dcdc78389d8d0ae7c248f013fbb1abc6768a0d999c8
7
- data.tar.gz: c747288209536e557565cdf470f2e12c5f786f1137388548af3fabfdbd523260bdf68b0c5b37adf0b0ddb4fdb3ea749e84d16f78eb9abb5bdee671971750c7d8
6
+ metadata.gz: d4bf38be75e38c3e9fdabdac8220b0ec283a7828778c9d1aaa6c084eed3a31ad677d12ef23d59aeb83188f258f6436d2ac50a6f1240e0dbbcdd01d7476694b5a
7
+ data.tar.gz: 6fd1b23cf9c7d1600ddf239616dbc86253de33a2b1ee73a82892f22cef0af1010920582a76ef5e1995d1188e451980700427cc932b261fdc99fcba9c0ba79914
data/CHANGELOG.md CHANGED
@@ -1,3 +1,203 @@
1
+ ## Rails 4.2.11.3 (May 15, 2020) ##
2
+
3
+ * No changes.
4
+
5
+
6
+ ## Rails 4.2.11.2 (May 15, 2020) ##
7
+
8
+ * No changes.
9
+
10
+
11
+ ## Rails 4.2.11.1 (March 11, 2019) ##
12
+
13
+ * No changes.
14
+
15
+
16
+ ## Rails 4.2.11 (November 27, 2018) ##
17
+
18
+ * No changes.
19
+
20
+
21
+ ## Rails 4.2.10 (September 27, 2017) ##
22
+
23
+ * No changes.
24
+
25
+
26
+ ## Rails 4.2.9 (June 26, 2017) ##
27
+
28
+ * Fixed bug in `DateAndTime::Compatibility#to_time` that caused it to
29
+ raise `RuntimeError: can't modify frozen Time` when called on any frozen `Time`.
30
+ Properly pass through the frozen `Time` or `ActiveSupport::TimeWithZone` object
31
+ when calling `#to_time`.
32
+
33
+ *Kevin McPhillips* & *Andrew White*
34
+
35
+ * Restore the return type of `DateTime#utc`
36
+
37
+ In Rails 5.0 the return type of `DateTime#utc` was changed to `Time` to be
38
+ consistent with the new `DateTime#localtime` method. When these changes were
39
+ backported in #27553 this inadvertently changed the return type in a patcn
40
+ release. Since `DateTime#localtime` was new in Rails 4.2.8 it's okay to
41
+ restore the return type of `DateTime#utc` but keep `DateTime#localtime` as
42
+ returning `Time` without breaking backwards compatibility.
43
+
44
+ *Andrew White*
45
+
46
+ * In Core Extensions, make `MarshalWithAutoloading#load` pass through the second, optional
47
+ argument for `Marshal#load( source [, proc] )`. This way we don't have to do
48
+ `Marshal.method(:load).super_method.call(sourse, proc)` just to be able to pass a proc.
49
+
50
+ *Jeff Latz*
51
+
52
+ * Cache `ActiveSupport::TimeWithZone#to_datetime` before freezing.
53
+
54
+ *Adam Rice*
55
+
56
+ * `AS::Testing::TimeHelpers#travel_to` now changes `DateTime.now` as well as
57
+ `Time.now` and `Date.today`.
58
+
59
+ *Yuki Nishijima*
60
+
61
+
62
+ ## Rails 4.2.8 (February 21, 2017) ##
63
+
64
+ * Make `getlocal` and `getutc` always return instances of `Time` for
65
+ `ActiveSupport::TimeWithZone` and `DateTime`. This eliminates a possible
66
+ stack level too deep error in `to_time` where `ActiveSupport::TimeWithZone`
67
+ was wrapping a `DateTime` instance. As a consequence of this the internal
68
+ time value in `ActiveSupport::TimeWithZone` is now always an instance of
69
+ `Time` in the UTC timezone, whether that's as the UTC time directly or
70
+ a representation of the local time in the timezone. There should be no
71
+ consequences of this internal change and if there are it's a bug due to
72
+ leaky abstractions.
73
+
74
+ *Andrew White*
75
+
76
+ * Add `DateTime#subsec` to return the fraction of a second as a `Rational`.
77
+
78
+ *Andrew White*
79
+
80
+ * Add additional aliases for `DateTime#utc` to mirror the ones on
81
+ `ActiveSupport::TimeWithZone` and `Time`.
82
+
83
+ *Andrew White*
84
+
85
+ * Add `DateTime#localtime` to return an instance of `Time` in the system's
86
+ local timezone. Also aliased to `getlocal`.
87
+
88
+ *Andrew White*, *Yuichiro Kaneko*
89
+
90
+ * Add `Time#sec_fraction` to return the fraction of a second as a `Rational`.
91
+
92
+ *Andrew White*
93
+
94
+ * Add `ActiveSupport.to_time_preserves_timezone` config option to control
95
+ how `to_time` handles timezones. In Ruby 2.4+ the behavior will change
96
+ from converting to the local system timezone, to preserving the timezone
97
+ of the receiver. This config option defaults to false so that apps made
98
+ with earlier versions of Rails are not affected when upgrading, e.g:
99
+
100
+ >> ENV['TZ'] = 'US/Eastern'
101
+
102
+ >> "2016-04-23T10:23:12.000Z".to_time
103
+ => "2016-04-23T06:23:12.000-04:00"
104
+
105
+ >> ActiveSupport.to_time_preserves_timezone = true
106
+
107
+ >> "2016-04-23T10:23:12.000Z".to_time
108
+ => "2016-04-23T10:23:12.000Z"
109
+
110
+ Fixes #24617.
111
+
112
+ *Andrew White*
113
+
114
+ * Add `init_with` to `ActiveSupport::TimeWithZone` and `ActiveSupport::TimeZone`
115
+
116
+ It is helpful to be able to run apps concurrently written in successive
117
+ versions of Rails to aid migration, e.g. run Rails 4.2 and 5.0 variants
118
+ of your application at the same time to carry out A/B testing.
119
+
120
+ To do this serialization formats need to be cross compatible and the
121
+ change in 3aa26cf didn't meet this criteria because the Psych loader
122
+ checks for the existence of `init_with` before setting the instance
123
+ variables and the wrapping behavior of `ActiveSupport::TimeWithZone`
124
+ tries to see if the `Time` instance responds to `init_with` before the
125
+ `@time` variable is set.
126
+
127
+ To fix this we backported just the `init_with` behavior from the change
128
+ in 3aa26cf. If the revived instance is then written out to YAML again
129
+ it will revert to the default Rails 4.2 behavior of converting it to
130
+ a UTC timestamp string.
131
+
132
+ Fixes #26296.
133
+
134
+ *Andrew White*
135
+
136
+ * Fix `ActiveSupport::TimeWithZone#in` across DST boundaries.
137
+
138
+ Previously calls to `in` were being sent to the non-DST aware
139
+ method `Time#since` via `method_missing`. It is now aliased to
140
+ the DST aware `ActiveSupport::TimeWithZone#since` which handles
141
+ transitions across DST boundaries, e.g:
142
+
143
+ Time.zone = "US/Eastern"
144
+
145
+ t = Time.zone.local(2016,11,6,1)
146
+ # => Sun, 06 Nov 2016 01:00:00 EDT -05:00
147
+
148
+ t.in(1.hour)
149
+ # => Sun, 06 Nov 2016 01:00:00 EST -05:00
150
+
151
+ Fixes #26580.
152
+
153
+ *Thomas Balthazar*
154
+
155
+
156
+ ## Rails 4.2.7 (July 12, 2016) ##
157
+
158
+ * Fixed `ActiveSupport::Logger.broadcast` so that calls to `#silence` now
159
+ properly delegate to all loggers. Silencing now properly suppresses logging
160
+ to both the log and the console.
161
+
162
+ *Kevin McPhillips*
163
+
164
+ * Backported `ActiveSupport::LoggerThreadSafeLevel`. Assigning the
165
+ `Rails.logger.level` is now thread safe.
166
+
167
+ *Kevin McPhillips*
168
+
169
+ * Fixed a problem with ActiveSupport::SafeBuffer.titleize calling capitalize
170
+ on nil.
171
+
172
+ *Brian McManus*
173
+
174
+ * Time zones: Ensure that the UTC offset reflects DST changes that occurred
175
+ since the app started. Removes UTC offset caching, reducing performance,
176
+ but this is still relatively quick and isn't in any hot paths.
177
+
178
+ *Alexey Shein*
179
+
180
+ * Prevent `Marshal.load` from looping infinitely when trying to autoload a constant
181
+ which resolves to a different name.
182
+
183
+ *Olek Janiszewski*
184
+
185
+
186
+ ## Rails 4.2.6 (March 07, 2016) ##
187
+
188
+ * No changes.
189
+
190
+
191
+ ## Rails 4.2.5.2 (February 26, 2016) ##
192
+
193
+ * No changes.
194
+
195
+
196
+ ## Rails 4.2.5.1 (January 25, 2015) ##
197
+
198
+ * No changes.
199
+
200
+
1
201
  ## Rails 4.2.5 (November 12, 2015) ##
2
202
 
3
203
  * Fix `TimeWithZone#eql?` to properly handle `TimeWithZone` created from `DateTime`:
@@ -67,7 +67,7 @@ module ActiveSupport
67
67
  options = names.extract_options!
68
68
  options = merged_options(options)
69
69
  keys_to_names = Hash[names.map{|name| [escape_key(namespaced_key(name, options)), name]}]
70
- raw_values = @data.get_multi(keys_to_names.keys, :raw => true)
70
+ raw_values = @data.get_multi(keys_to_names.keys)
71
71
  values = {}
72
72
  raw_values.each do |key, value|
73
73
  entry = deserialize_entry(value)
@@ -770,7 +770,7 @@ module ActiveSupport
770
770
  options = names.extract_options!
771
771
 
772
772
  names.each do |name|
773
- class_attribute "_#{name}_callbacks"
773
+ class_attribute "_#{name}_callbacks", instance_writer: false
774
774
  set_callbacks name, CallbackChain.new(name, options)
775
775
 
776
776
  module_eval <<-RUBY, __FILE__, __LINE__ + 1
@@ -25,8 +25,6 @@ class Class
25
25
 
26
26
  # Returns an array with the direct children of +self+.
27
27
  #
28
- # Integer.subclasses # => [Fixnum, Bignum]
29
- #
30
28
  # class Foo; end
31
29
  # class Bar < Foo; end
32
30
  # class Baz < Bar; end
@@ -0,0 +1,15 @@
1
+ require 'active_support/core_ext/module/attribute_accessors'
2
+ require 'active_support/core_ext/module/remove_method'
3
+
4
+ module DateAndTime
5
+ module Compatibility
6
+ # If true, +to_time+ preserves the timezone offset of receiver.
7
+ #
8
+ # NOTE: With Ruby 2.4+ the default for +to_time+ changed from
9
+ # converting to the local system time, to preserving the offset
10
+ # of the receiver. For backwards compatibility we're overriding
11
+ # this behavior, but new apps will have an initializer that sets
12
+ # this to true, because the new behavior is preferred.
13
+ mattr_accessor(:preserve_timezone, instance_writer: false) { false }
14
+ end
15
+ end
@@ -24,6 +24,13 @@ class DateTime
24
24
  end_of_day.to_i - to_i
25
25
  end
26
26
 
27
+ # Returns the fraction of a second as a +Rational+
28
+ #
29
+ # DateTime.new(2012, 8, 29, 0, 0, 0.5).subsec # => (1/2)
30
+ def subsec
31
+ sec_fraction
32
+ end
33
+
27
34
  # Returns a new DateTime where one or more of the elements have been changed
28
35
  # according to the +options+ parameter. The time options (<tt>:hour</tt>,
29
36
  # <tt>:min</tt>, <tt>:sec</tt>) reset cascadingly, so if only the hour is
@@ -139,14 +146,27 @@ class DateTime
139
146
  end
140
147
  alias :at_end_of_minute :end_of_minute
141
148
 
142
- # Adjusts DateTime to UTC by adding its offset value; offset is set to 0.
149
+ # Returns a <tt>Time</tt> instance of the simultaneous time in the system timezone.
150
+ def localtime(utc_offset = nil)
151
+ utc = new_offset(0)
152
+
153
+ Time.utc(
154
+ utc.year, utc.month, utc.day,
155
+ utc.hour, utc.min, utc.sec + utc.sec_fraction
156
+ ).getlocal(utc_offset)
157
+ end
158
+ alias_method :getlocal, :localtime
159
+
160
+ # Returns a <tt>DateTime</tt> instance of the simultaneous time in the UTC timezone.
143
161
  #
144
162
  # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)) # => Mon, 21 Feb 2005 10:11:12 -0600
145
- # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 +0000
163
+ # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 UTC
146
164
  def utc
147
165
  new_offset(0)
148
166
  end
167
+ alias_method :getgm, :utc
149
168
  alias_method :getutc, :utc
169
+ alias_method :gmtime, :utc
150
170
 
151
171
  # Returns +true+ if <tt>offset == 0</tt>.
152
172
  def utc?
@@ -0,0 +1,16 @@
1
+ require 'active_support/core_ext/date_and_time/compatibility'
2
+ require 'active_support/core_ext/module/remove_method'
3
+
4
+ class DateTime
5
+ include DateAndTime::Compatibility
6
+
7
+ remove_possible_method :to_time
8
+
9
+ # Either return an instance of `Time` with the same UTC offset
10
+ # as +self+ or an instance of `Time` representing the same time
11
+ # in the the local system timezone depending on the setting of
12
+ # on the setting of +ActiveSupport.to_time_preserves_timezone+.
13
+ def to_time
14
+ preserve_timezone ? getlocal(utc_offset) : getlocal
15
+ end
16
+ end
@@ -1,4 +1,5 @@
1
1
  require 'active_support/core_ext/date_time/acts_like'
2
2
  require 'active_support/core_ext/date_time/calculations'
3
+ require 'active_support/core_ext/date_time/compatibility'
3
4
  require 'active_support/core_ext/date_time/conversions'
4
5
  require 'active_support/core_ext/date_time/zones'
@@ -78,3 +78,19 @@ class Range #:nodoc:
78
78
  end
79
79
  end
80
80
  end
81
+
82
+ # Array#sum was added in Ruby 2.4 but it only works with Numeric elements.
83
+ #
84
+ # We tried shimming it to attempt the fast native method, rescue TypeError,
85
+ # and fall back to the compatible implementation, but that's much slower than
86
+ # just calling the compat method in the first place.
87
+ if Array.instance_methods(false).include?(:sum) && !(%w[a].sum rescue false)
88
+ class Array
89
+ remove_method :sum
90
+
91
+ def sum(*args) #:nodoc:
92
+ # Use Enumerable#sum instead.
93
+ super
94
+ end
95
+ end
96
+ end
@@ -1,20 +1,24 @@
1
1
  class Hash
2
- # Returns a hash with non +nil+ values.
3
- #
4
- # hash = { a: true, b: false, c: nil}
5
- # hash.compact # => { a: true, b: false}
6
- # hash # => { a: true, b: false, c: nil}
7
- # { c: nil }.compact # => {}
8
- def compact
9
- self.select { |_, value| !value.nil? }
2
+ unless Hash.instance_methods(false).include?(:compact)
3
+ # Returns a hash with non +nil+ values.
4
+ #
5
+ # hash = { a: true, b: false, c: nil}
6
+ # hash.compact # => { a: true, b: false}
7
+ # hash # => { a: true, b: false, c: nil}
8
+ # { c: nil }.compact # => {}
9
+ def compact
10
+ self.select { |_, value| !value.nil? }
11
+ end
10
12
  end
11
13
 
12
- # Replaces current hash with non +nil+ values.
13
- #
14
- # hash = { a: true, b: false, c: nil}
15
- # hash.compact! # => { a: true, b: false}
16
- # hash # => { a: true, b: false}
17
- def compact!
18
- self.reject! { |_, value| value.nil? }
14
+ unless Hash.instance_methods(false).include?(:compact!)
15
+ # Replaces current hash with non +nil+ values.
16
+ #
17
+ # hash = { a: true, b: false, c: nil}
18
+ # hash.compact! # => { a: true, b: false}
19
+ # hash # => { a: true, b: false}
20
+ def compact!
21
+ self.reject! { |_, value| value.nil? }
22
+ end
19
23
  end
20
24
  end
@@ -55,8 +55,7 @@ class Hash
55
55
  #
56
56
  # XML_TYPE_NAMES = {
57
57
  # "Symbol" => "symbol",
58
- # "Fixnum" => "integer",
59
- # "Bignum" => "integer",
58
+ # "Integer" => "integer",
60
59
  # "BigDecimal" => "decimal",
61
60
  # "Float" => "float",
62
61
  # "TrueClass" => "boolean",
@@ -11,7 +11,7 @@ class Hash
11
11
  result[key] = yield(value)
12
12
  end
13
13
  result
14
- end
14
+ end unless method_defined? :transform_values
15
15
 
16
16
  # Destructive +transform_values+
17
17
  def transform_values!
@@ -19,5 +19,5 @@ class Hash
19
19
  each do |key, value|
20
20
  self[key] = yield(value)
21
21
  end
22
- end
22
+ end unless method_defined? :transform_values!
23
23
  end
@@ -2,13 +2,16 @@ require 'active_support/core_ext/module/aliasing'
2
2
 
3
3
  module Marshal
4
4
  class << self
5
- def load_with_autoloading(source)
6
- load_without_autoloading(source)
5
+ def load_with_autoloading(source, proc = nil)
6
+ load_without_autoloading(source, proc)
7
7
  rescue ArgumentError, NameError => exc
8
- if exc.message.match(%r|undefined class/module (.+)|)
8
+ if exc.message.match(%r|undefined class/module (.+?)(::)?\z|)
9
9
  # try loading the class/module
10
- $1.constantize
11
- # if it is a IO we need to go back to read the object
10
+ loaded = $1.constantize
11
+
12
+ raise unless $1 == loaded.name
13
+
14
+ # if it is an IO we need to go back to read the object
12
15
  source.rewind if source.respond_to?(:rewind)
13
16
  retry
14
17
  else
@@ -11,6 +11,14 @@ class Module
11
11
  return self super then true undef unless until when while yield)
12
12
  ).freeze
13
13
 
14
+ DELEGATION_RESERVED_KEYWORDS = Set.new(
15
+ %w(_ arg args block)
16
+ )
17
+
18
+ DELEGATION_RESERVED_METHOD_NAMES = Set.new(
19
+ RUBY_RESERVED_WORDS + DELEGATION_RESERVED_KEYWORDS
20
+ ).freeze
21
+
14
22
  # Provides a +delegate+ class method to easily expose contained objects'
15
23
  # public methods as your own.
16
24
  #
@@ -118,7 +118,15 @@ class Numeric
118
118
  end
119
119
  end
120
120
 
121
- [Float, Fixnum, Bignum, BigDecimal].each do |klass|
121
+ klasses = [Float, BigDecimal]
122
+ # Ruby 2.4+ unifies Fixnum & Bignum into Integer.
123
+ if 0.class == Integer
124
+ klasses << Integer
125
+ else
126
+ klasses << Fixnum << Bignum
127
+ end
128
+
129
+ klasses.each do |klass|
122
130
  klass.send(:alias_method, :to_default_s, :to_s)
123
131
 
124
132
  klass.send(:define_method, :to_s) do |*args|
@@ -1,7 +1,7 @@
1
1
  #--
2
- # Most objects are cloneable, but not all. For example you can't dup +nil+:
2
+ # Most objects are cloneable, but not all. For example you can't dup methods:
3
3
  #
4
- # nil.dup # => TypeError: can't dup NilClass
4
+ # method(:puts).dup # => TypeError: allocator undefined for Method
5
5
  #
6
6
  # Classes may signal their instances are not duplicable removing +dup+/+clone+
7
7
  # or raising exceptions from them. So, to dup an arbitrary object you normally
@@ -27,52 +27,78 @@ class Object
27
27
  end
28
28
 
29
29
  class NilClass
30
- # +nil+ is not duplicable:
31
- #
32
- # nil.duplicable? # => false
33
- # nil.dup # => TypeError: can't dup NilClass
34
- def duplicable?
35
- false
30
+ begin
31
+ nil.dup
32
+ rescue TypeError
33
+
34
+ # +nil+ is not duplicable:
35
+ #
36
+ # nil.duplicable? # => false
37
+ # nil.dup # => TypeError: can't dup NilClass
38
+ def duplicable?
39
+ false
40
+ end
36
41
  end
37
42
  end
38
43
 
39
44
  class FalseClass
40
- # +false+ is not duplicable:
41
- #
42
- # false.duplicable? # => false
43
- # false.dup # => TypeError: can't dup FalseClass
44
- def duplicable?
45
- false
45
+ begin
46
+ false.dup
47
+ rescue TypeError
48
+
49
+ # +false+ is not duplicable:
50
+ #
51
+ # false.duplicable? # => false
52
+ # false.dup # => TypeError: can't dup FalseClass
53
+ def duplicable?
54
+ false
55
+ end
46
56
  end
47
57
  end
48
58
 
49
59
  class TrueClass
50
- # +true+ is not duplicable:
51
- #
52
- # true.duplicable? # => false
53
- # true.dup # => TypeError: can't dup TrueClass
54
- def duplicable?
55
- false
60
+ begin
61
+ true.dup
62
+ rescue TypeError
63
+
64
+ # +true+ is not duplicable:
65
+ #
66
+ # true.duplicable? # => false
67
+ # true.dup # => TypeError: can't dup TrueClass
68
+ def duplicable?
69
+ false
70
+ end
56
71
  end
57
72
  end
58
73
 
59
74
  class Symbol
60
- # Symbols are not duplicable:
61
- #
62
- # :my_symbol.duplicable? # => false
63
- # :my_symbol.dup # => TypeError: can't dup Symbol
64
- def duplicable?
65
- false
75
+ begin
76
+ :symbol.dup # Ruby 2.4.x.
77
+ 'symbol_from_string'.to_sym.dup # Some symbols can't `dup` in Ruby 2.4.0.
78
+ rescue TypeError
79
+
80
+ # Symbols are not duplicable:
81
+ #
82
+ # :my_symbol.duplicable? # => false
83
+ # :my_symbol.dup # => TypeError: can't dup Symbol
84
+ def duplicable?
85
+ false
86
+ end
66
87
  end
67
88
  end
68
89
 
69
90
  class Numeric
70
- # Numbers are not duplicable:
71
- #
72
- # 3.duplicable? # => false
73
- # 3.dup # => TypeError: can't dup Fixnum
74
- def duplicable?
75
- false
91
+ begin
92
+ 1.dup
93
+ rescue TypeError
94
+
95
+ # Numbers are not duplicable:
96
+ #
97
+ # 3.duplicable? # => false
98
+ # 3.dup # => TypeError: can't dup Integer
99
+ def duplicable?
100
+ false
101
+ end
76
102
  end
77
103
  end
78
104
 
@@ -1,5 +1,5 @@
1
1
  class String
2
- # If you pass a single Fixnum, returns a substring of one character at that
2
+ # If you pass a single integer, returns a substring of one character at that
3
3
  # position. The first character of the string is at position 0, the next at
4
4
  # position 1, and so on. If a range is supplied, a substring containing
5
5
  # characters at offsets given by the range is returned. In both cases, if an
@@ -31,7 +31,7 @@ class String
31
31
  parts.fetch(:offset, form == :utc ? 0 : nil)
32
32
  )
33
33
 
34
- form == :utc ? time.utc : time.getlocal
34
+ form == :utc ? time.utc : time.to_time
35
35
  end
36
36
 
37
37
  # Converts a string to a Date value.
@@ -63,6 +63,13 @@ class Time
63
63
  end_of_day.to_i - to_i
64
64
  end
65
65
 
66
+ # Returns the fraction of a second as a +Rational+
67
+ #
68
+ # Time.new(2012, 8, 29, 0, 0, 0.5).sec_fraction # => (1/2)
69
+ def sec_fraction
70
+ subsec
71
+ end
72
+
66
73
  # Returns a new Time where one or more of the elements have been changed according
67
74
  # to the +options+ parameter. The time options (<tt>:hour</tt>, <tt>:min</tt>,
68
75
  # <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly, so if only
@@ -250,7 +257,9 @@ class Time
250
257
  # can be chronologically compared with a Time
251
258
  def compare_with_coercion(other)
252
259
  # we're avoiding Time#to_datetime cause it's expensive
253
- if other.is_a?(Time)
260
+ if other.class == Time
261
+ compare_without_coercion(other)
262
+ elsif other.is_a?(Time)
254
263
  compare_without_coercion(other.to_time)
255
264
  else
256
265
  to_datetime <=> other
@@ -0,0 +1,14 @@
1
+ require "active_support/core_ext/date_and_time/compatibility"
2
+ require "active_support/core_ext/module/remove_method"
3
+
4
+ class Time
5
+ include DateAndTime::Compatibility
6
+
7
+ remove_possible_method :to_time
8
+
9
+ # Either return +self+ or the time in the local system timezone depending
10
+ # on the setting of +ActiveSupport.to_time_preserves_timezone+.
11
+ def to_time
12
+ preserve_timezone ? self : getlocal
13
+ end
14
+ end
@@ -1,5 +1,6 @@
1
1
  require 'active_support/core_ext/time/acts_like'
2
2
  require 'active_support/core_ext/time/calculations'
3
+ require 'active_support/core_ext/time/compatibility'
3
4
  require 'active_support/core_ext/time/conversions'
4
5
  require 'active_support/core_ext/time/marshal'
5
6
  require 'active_support/core_ext/time/zones'