activesupport 5.1.1 → 5.1.2.rc1

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8aa2e16d1dbeb37a850d4f29b9976e2b97af04cb
4
- data.tar.gz: b9d37cfff133a4bf90d61b3f9c2e20a42e68d5eb
3
+ metadata.gz: 93d2cfe880c83ec575177cb50412397a4c7058cc
4
+ data.tar.gz: 1f36f1d92087b31345ac6f3250da648d0959643b
5
5
  SHA512:
6
- metadata.gz: 7428f4f737d838eca82d1ea3efdee001fd6a8d3f88ed244e1ce036d7adaaa7fc2ac833723a05ed647a34284345b3de4d27b6cbd6401dfef1664acb1ac0a857fa
7
- data.tar.gz: 694198ea6585501a6c0cfa56aee42c94811c0d05b3e83a5b2cac9bcf3650cba8cef5a9484fd44fa58705c2a166ead565f2580e040b151473607eb5e3171ad81a
6
+ metadata.gz: 97cb325630df684e61978d04c9c68a10f728bf1ad56cc49170d22a9cf89e606dbcbf9dadb7075aaf6f698ffb5e2455b6a2a9776547196aec2e76a262c60f8485
7
+ data.tar.gz: 8de7d7dbc0beb11270d7448217160cf50accd9616749378fcbc99eb78d6f7fa416f75eb30de1c4f9a5bf6ad2867d53f9c41359c2320a372bc1fb68c95e55606a
@@ -1,3 +1,39 @@
1
+ ## Rails 5.1.2.rc1 (June 20, 2017) ##
2
+
3
+ * Cache: Restore the `options = nil` argument for `LocalStore#clear`
4
+ that was removed in 5.1.0. Restores compatibility with backends that
5
+ take an options argument and use the local cache strategy.
6
+
7
+ *Jeremy Daer*
8
+
9
+ * Fix implicit coercion calculations with scalars and durations
10
+
11
+ Previously calculations where the scalar is first would be converted to a duration
12
+ of seconds but this causes issues with dates being converted to times, e.g:
13
+
14
+ Time.zone = "Beijing" # => Asia/Shanghai
15
+ date = Date.civil(2017, 5, 20) # => Mon, 20 May 2017
16
+ 2 * 1.day # => 172800 seconds
17
+ date + 2 * 1.day # => Mon, 22 May 2017 00:00:00 CST +08:00
18
+
19
+ Now the `ActiveSupport::Duration::Scalar` calculation methods will try to maintain
20
+ the part structure of the duration where possible, e.g:
21
+
22
+ Time.zone = "Beijing" # => Asia/Shanghai
23
+ date = Date.civil(2017, 5, 20) # => Mon, 20 May 2017
24
+ 2 * 1.day # => 2 days
25
+ date + 2 * 1.day # => Mon, 22 May 2017
26
+
27
+ Fixes #29160, #28970.
28
+
29
+ *Andrew White*
30
+
31
+
32
+ ## Rails 5.1.1 (May 12, 2017) ##
33
+
34
+ * No changes.
35
+
36
+
1
37
  ## Rails 5.1.0 (April 27, 2017) ##
2
38
 
3
39
  * `ActiveSupport::EventedFileUpdateChecker` no longer listens to
@@ -466,7 +466,7 @@ module ActiveSupport
466
466
  # The options hash is passed to the underlying cache implementation.
467
467
  #
468
468
  # All implementations may not support this method.
469
- def clear
469
+ def clear(options = nil)
470
470
  raise NotImplementedError.new("#{self.class.name} does not support clear")
471
471
  end
472
472
 
@@ -27,7 +27,7 @@ module ActiveSupport
27
27
  # Deletes all items from the cache. In this case it deletes all the entries in the specified
28
28
  # file store directory except for .keep or .gitkeep. Be careful which directory is specified in your
29
29
  # config file when using +FileStore+ because everything in that directory will be deleted.
30
- def clear
30
+ def clear(options = nil)
31
31
  root_dirs = exclude_from(cache_path, EXCLUDED_DIRS + GITKEEP_FILES)
32
32
  FileUtils.rm_r(root_dirs.collect { |f| File.join(cache_path, f) })
33
33
  rescue Errno::ENOENT
@@ -44,7 +44,7 @@ module ActiveSupport
44
44
  yield
45
45
  end
46
46
 
47
- def clear
47
+ def clear(options = nil)
48
48
  @data.clear
49
49
  end
50
50
 
@@ -79,9 +79,9 @@ module ActiveSupport
79
79
  local_cache_key)
80
80
  end
81
81
 
82
- def clear # :nodoc:
82
+ def clear(options = nil) # :nodoc:
83
83
  return super unless cache = local_cache
84
- cache.clear
84
+ cache.clear(options)
85
85
  super
86
86
  end
87
87
 
@@ -124,21 +124,31 @@ class Method
124
124
  end
125
125
 
126
126
  class Complex
127
- # Complexes are not duplicable:
128
- #
129
- # Complex(1).duplicable? # => false
130
- # Complex(1).dup # => TypeError: can't copy Complex
131
- def duplicable?
132
- false
127
+ begin
128
+ Complex(1).dup
129
+ rescue TypeError
130
+
131
+ # Complexes are not duplicable for RUBY_VERSION < 2.5.0:
132
+ #
133
+ # Complex(1).duplicable? # => false
134
+ # Complex(1).dup # => TypeError: can't copy Complex
135
+ def duplicable?
136
+ false
137
+ end
133
138
  end
134
139
  end
135
140
 
136
141
  class Rational
137
- # Rationals are not duplicable:
138
- #
139
- # Rational(1).duplicable? # => false
140
- # Rational(1).dup # => TypeError: can't copy Rational
141
- def duplicable?
142
- false
142
+ begin
143
+ Rational(1).dup
144
+ rescue TypeError
145
+
146
+ # Rationals are not duplicable for RUBY_VERSION < 2.5.0:
147
+ #
148
+ # Rational(1).duplicable? # => false
149
+ # Rational(1).dup # => TypeError: can't copy Rational
150
+ def duplicable?
151
+ false
152
+ end
143
153
  end
144
154
  end
@@ -37,27 +37,56 @@ module ActiveSupport
37
37
  end
38
38
 
39
39
  def +(other)
40
- calculate(:+, other)
40
+ if Duration === other
41
+ seconds = value + other.parts[:seconds]
42
+ new_parts = other.parts.merge(seconds: seconds)
43
+ new_value = value + other.value
44
+
45
+ Duration.new(new_value, new_parts)
46
+ else
47
+ calculate(:+, other)
48
+ end
41
49
  end
42
50
 
43
51
  def -(other)
44
- calculate(:-, other)
52
+ if Duration === other
53
+ seconds = value - other.parts[:seconds]
54
+ new_parts = other.parts.map { |part, other_value| [part, -other_value] }.to_h
55
+ new_parts = new_parts.merge(seconds: seconds)
56
+ new_value = value - other.value
57
+
58
+ Duration.new(new_value, new_parts)
59
+ else
60
+ calculate(:-, other)
61
+ end
45
62
  end
46
63
 
47
64
  def *(other)
48
- calculate(:*, other)
65
+ if Duration === other
66
+ new_parts = other.parts.map { |part, other_value| [part, value * other_value] }.to_h
67
+ new_value = value * other.value
68
+
69
+ Duration.new(new_value, new_parts)
70
+ else
71
+ calculate(:*, other)
72
+ end
49
73
  end
50
74
 
51
75
  def /(other)
52
- calculate(:/, other)
76
+ if Duration === other
77
+ new_parts = other.parts.map { |part, other_value| [part, value / other_value] }.to_h
78
+ new_value = new_parts.inject(0) { |total, (part, value)| total + value * Duration::PARTS_IN_SECONDS[part] }
79
+
80
+ Duration.new(new_value, new_parts)
81
+ else
82
+ calculate(:/, other)
83
+ end
53
84
  end
54
85
 
55
86
  private
56
87
  def calculate(op, other)
57
88
  if Scalar === other
58
89
  Scalar.new(value.public_send(op, other.value))
59
- elsif Duration === other
60
- Duration.seconds(value).public_send(op, other)
61
90
  elsif Numeric === other
62
91
  Scalar.new(value.public_send(op, other))
63
92
  else
@@ -7,8 +7,8 @@ module ActiveSupport
7
7
  module VERSION
8
8
  MAJOR = 5
9
9
  MINOR = 1
10
- TINY = 1
11
- PRE = nil
10
+ TINY = 2
11
+ PRE = "rc1"
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
14
  end
@@ -81,8 +81,10 @@ module ActiveSupport
81
81
 
82
82
  def finish(name, id, payload)
83
83
  super if logger
84
- rescue Exception => e
85
- logger.error "Could not log #{name.inspect} event. #{e.class}: #{e.message} #{e.backtrace}"
84
+ rescue => e
85
+ if logger
86
+ logger.error "Could not log #{name.inspect} event. #{e.class}: #{e.message} #{e.backtrace}"
87
+ end
86
88
  end
87
89
 
88
90
  private
@@ -115,7 +115,7 @@ module ActiveSupport
115
115
  # Currently the OpenSSL bindings do not raise an error if auth_tag is
116
116
  # truncated, which would allow an attacker to easily forge it. See
117
117
  # https://github.com/ruby/openssl/issues/63
118
- raise InvalidMessage if aead_mode? && auth_tag.bytes.length != 16
118
+ raise InvalidMessage if aead_mode? && (auth_tag.nil? || auth_tag.bytes.length != 16)
119
119
 
120
120
  cipher.decrypt
121
121
  cipher.key = @secret
@@ -4,6 +4,7 @@ module ActiveSupport
4
4
 
5
5
  eager_autoload do
6
6
  autoload :NumberConverter
7
+ autoload :RoundingHelper
7
8
  autoload :NumberToRoundedConverter
8
9
  autoload :NumberToDelimitedConverter
9
10
  autoload :NumberToHumanConverter
@@ -9,6 +9,7 @@ module ActiveSupport
9
9
  self.validate_float = true
10
10
 
11
11
  def convert # :nodoc:
12
+ @number = RoundingHelper.new(options).round(number)
12
13
  @number = Float(number)
13
14
 
14
15
  # for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
@@ -20,10 +21,7 @@ module ActiveSupport
20
21
  exponent = calculate_exponent(units)
21
22
  @number = number / (10**exponent)
22
23
 
23
- until (rounded_number = NumberToRoundedConverter.convert(number, options)) != NumberToRoundedConverter.convert(1000, options)
24
- @number = number / 1000.0
25
- exponent += 3
26
- end
24
+ rounded_number = NumberToRoundedConverter.convert(number, options)
27
25
  unit = determine_unit(units, exponent)
28
26
  format.gsub("%n".freeze, rounded_number).gsub("%u".freeze, unit).strip
29
27
  end
@@ -5,26 +5,14 @@ module ActiveSupport
5
5
  self.validate_float = true
6
6
 
7
7
  def convert
8
- precision = options.delete :precision
8
+ helper = RoundingHelper.new(options)
9
+ rounded_number = helper.round(number)
9
10
 
10
- if precision
11
- case number
12
- when Float, String
13
- @number = BigDecimal(number.to_s)
14
- when Rational
15
- @number = BigDecimal(number, digit_count(number.to_i) + precision)
16
- else
17
- @number = number.to_d
18
- end
19
-
20
- if options.delete(:significant) && precision > 0
21
- digits, rounded_number = digits_and_rounded_number(precision)
11
+ if precision = options[:precision]
12
+ if options[:significant] && precision > 0
13
+ digits = helper.digit_count(rounded_number)
22
14
  precision -= digits
23
15
  precision = 0 if precision < 0 # don't let it be negative
24
- else
25
- rounded_number = number.round(precision)
26
- rounded_number = rounded_number.to_i if precision == 0 && rounded_number.finite?
27
- rounded_number = rounded_number.abs if rounded_number.zero? # prevent showing negative zeros
28
16
  end
29
17
 
30
18
  formatted_string =
@@ -38,7 +26,7 @@ module ActiveSupport
38
26
  "%00.#{precision}f" % rounded_number
39
27
  end
40
28
  else
41
- formatted_string = number
29
+ formatted_string = rounded_number
42
30
  end
43
31
 
44
32
  delimited_number = NumberToDelimitedConverter.convert(formatted_string, options)
@@ -79,14 +67,6 @@ module ActiveSupport
79
67
  number
80
68
  end
81
69
  end
82
-
83
- def absolute_number(number)
84
- number.respond_to?(:abs) ? number.abs : number.to_d.abs
85
- end
86
-
87
- def zero?
88
- number.respond_to?(:zero?) ? number.zero? : number.to_d.zero?
89
- end
90
70
  end
91
71
  end
92
72
  end
@@ -0,0 +1,64 @@
1
+ module ActiveSupport
2
+ module NumberHelper
3
+ class RoundingHelper # :nodoc:
4
+ attr_reader :options
5
+
6
+ def initialize(options)
7
+ @options = options
8
+ end
9
+
10
+ def round(number)
11
+ return number unless precision
12
+ number = convert_to_decimal(number)
13
+ if significant && precision > 0
14
+ round_significant(number)
15
+ else
16
+ round_without_significant(number)
17
+ end
18
+ end
19
+
20
+ def digit_count(number)
21
+ return 1 if number.zero?
22
+ (Math.log10(absolute_number(number)) + 1).floor
23
+ end
24
+
25
+ private
26
+ def round_without_significant(number)
27
+ number = number.round(precision)
28
+ number = number.to_i if precision == 0 && number.finite?
29
+ number = number.abs if number.zero? # prevent showing negative zeros
30
+ number
31
+ end
32
+
33
+ def round_significant(number)
34
+ return 0 if number.zero?
35
+ digits = digit_count(number)
36
+ multiplier = 10**(digits - precision)
37
+ (number / BigDecimal.new(multiplier.to_f.to_s)).round * multiplier
38
+ end
39
+
40
+ def convert_to_decimal(number)
41
+ case number
42
+ when Float, String
43
+ number = BigDecimal(number.to_s)
44
+ when Rational
45
+ number = BigDecimal(number, digit_count(number.to_i) + precision)
46
+ else
47
+ number = number.to_d
48
+ end
49
+ end
50
+
51
+ def precision
52
+ options[:precision]
53
+ end
54
+
55
+ def significant
56
+ options[:significant]
57
+ end
58
+
59
+ def absolute_number(number)
60
+ number.respond_to?(:abs) ? number.abs : number.to_d.abs
61
+ end
62
+ end
63
+ end
64
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activesupport
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.1
4
+ version: 5.1.2.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-12 00:00:00.000000000 Z
11
+ date: 2017-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -271,6 +271,7 @@ files:
271
271
  - lib/active_support/number_helper/number_to_percentage_converter.rb
272
272
  - lib/active_support/number_helper/number_to_phone_converter.rb
273
273
  - lib/active_support/number_helper/number_to_rounded_converter.rb
274
+ - lib/active_support/number_helper/rounding_helper.rb
274
275
  - lib/active_support/option_merger.rb
275
276
  - lib/active_support/ordered_hash.rb
276
277
  - lib/active_support/ordered_options.rb
@@ -326,15 +327,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
326
327
  version: 2.2.2
327
328
  required_rubygems_version: !ruby/object:Gem::Requirement
328
329
  requirements:
329
- - - ">="
330
+ - - ">"
330
331
  - !ruby/object:Gem::Version
331
- version: '0'
332
+ version: 1.3.1
332
333
  requirements: []
333
334
  rubyforge_project:
334
- rubygems_version: 2.6.10
335
+ rubygems_version: 2.6.12
335
336
  signing_key:
336
337
  specification_version: 4
337
338
  summary: A toolkit of support libraries and Ruby core extensions extracted from the
338
339
  Rails framework.
339
340
  test_files: []
340
- has_rdoc: