activesupport 4.2.11.3 → 5.0.0.beta1
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 +5 -5
- data/CHANGELOG.md +309 -485
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -3
- data/lib/active_support.rb +8 -15
- data/lib/active_support/array_inquirer.rb +44 -0
- data/lib/active_support/backtrace_cleaner.rb +1 -1
- data/lib/active_support/cache.rb +59 -72
- data/lib/active_support/cache/file_store.rb +27 -19
- data/lib/active_support/cache/mem_cache_store.rb +71 -60
- data/lib/active_support/cache/memory_store.rb +16 -21
- data/lib/active_support/cache/null_store.rb +1 -4
- data/lib/active_support/cache/strategy/local_cache.rb +31 -20
- data/lib/active_support/callbacks.rb +107 -111
- data/lib/active_support/concern.rb +1 -1
- data/lib/active_support/concurrency/latch.rb +7 -15
- data/lib/active_support/concurrency/share_lock.rb +142 -0
- data/lib/active_support/configurable.rb +1 -0
- data/lib/active_support/core_ext.rb +2 -1
- data/lib/active_support/core_ext/array.rb +1 -0
- data/lib/active_support/core_ext/array/access.rb +13 -1
- data/lib/active_support/core_ext/array/conversions.rb +6 -4
- data/lib/active_support/core_ext/array/inquiry.rb +17 -0
- data/lib/active_support/core_ext/array/wrap.rb +5 -4
- data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -10
- data/lib/active_support/core_ext/class.rb +0 -1
- data/lib/active_support/core_ext/class/attribute.rb +10 -9
- data/lib/active_support/core_ext/class/subclasses.rb +5 -2
- data/lib/active_support/core_ext/date.rb +1 -1
- data/lib/active_support/core_ext/date/blank.rb +12 -0
- data/lib/active_support/core_ext/date/calculations.rb +1 -1
- data/lib/active_support/core_ext/date/conversions.rb +3 -3
- data/lib/active_support/core_ext/date_and_time/calculations.rb +93 -27
- data/lib/active_support/core_ext/date_and_time/zones.rb +1 -2
- data/lib/active_support/core_ext/date_time.rb +1 -1
- data/lib/active_support/core_ext/date_time/blank.rb +12 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +7 -23
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
- data/lib/active_support/core_ext/enumerable.rb +27 -17
- data/lib/active_support/core_ext/file/atomic.rb +30 -25
- data/lib/active_support/core_ext/hash/compact.rb +15 -19
- data/lib/active_support/core_ext/hash/conversions.rb +21 -2
- data/lib/active_support/core_ext/hash/deep_merge.rb +1 -1
- data/lib/active_support/core_ext/hash/except.rb +9 -8
- data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -1
- data/lib/active_support/core_ext/hash/keys.rb +22 -18
- data/lib/active_support/core_ext/hash/slice.rb +1 -1
- data/lib/active_support/core_ext/hash/transform_values.rb +13 -7
- data/lib/active_support/core_ext/integer/time.rb +1 -1
- data/lib/active_support/core_ext/kernel.rb +0 -1
- data/lib/active_support/core_ext/kernel/debugger.rb +3 -10
- data/lib/active_support/core_ext/kernel/reporting.rb +0 -84
- data/lib/active_support/core_ext/load_error.rb +4 -2
- data/lib/active_support/core_ext/marshal.rb +8 -13
- data/lib/active_support/core_ext/module.rb +1 -0
- data/lib/active_support/core_ext/module/aliasing.rb +6 -1
- data/lib/active_support/core_ext/module/anonymous.rb +10 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -5
- data/lib/active_support/core_ext/module/attribute_accessors.rb +7 -7
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
- data/lib/active_support/core_ext/module/concerning.rb +4 -4
- data/lib/active_support/core_ext/module/delegation.rb +7 -14
- data/lib/active_support/core_ext/module/method_transplanting.rb +3 -13
- data/lib/active_support/core_ext/module/qualified_const.rb +30 -12
- data/lib/active_support/core_ext/module/remove_method.rb +23 -0
- data/lib/active_support/core_ext/name_error.rb +15 -2
- data/lib/active_support/core_ext/numeric.rb +1 -0
- data/lib/active_support/core_ext/numeric/bytes.rb +20 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +12 -23
- data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
- data/lib/active_support/core_ext/numeric/time.rb +20 -0
- data/lib/active_support/core_ext/object.rb +0 -1
- data/lib/active_support/core_ext/object/blank.rb +11 -2
- data/lib/active_support/core_ext/object/deep_dup.rb +10 -3
- data/lib/active_support/core_ext/object/duplicable.rb +39 -70
- data/lib/active_support/core_ext/object/inclusion.rb +2 -2
- data/lib/active_support/core_ext/object/instance_variables.rb +1 -1
- data/lib/active_support/core_ext/object/json.rb +9 -7
- data/lib/active_support/core_ext/object/to_query.rb +1 -1
- data/lib/active_support/core_ext/object/try.rb +67 -21
- data/lib/active_support/core_ext/object/with_options.rb +1 -1
- data/lib/active_support/core_ext/range/conversions.rb +18 -6
- data/lib/active_support/core_ext/range/each.rb +16 -18
- data/lib/active_support/core_ext/range/include_range.rb +20 -20
- data/lib/active_support/core_ext/securerandom.rb +23 -0
- data/lib/active_support/core_ext/string/access.rb +1 -1
- data/lib/active_support/core_ext/string/behavior.rb +1 -1
- data/lib/active_support/core_ext/string/conversions.rb +2 -2
- data/lib/active_support/core_ext/string/filters.rb +1 -2
- data/lib/active_support/core_ext/string/inflections.rb +23 -5
- data/lib/active_support/core_ext/string/multibyte.rb +11 -7
- data/lib/active_support/core_ext/string/output_safety.rb +8 -9
- data/lib/active_support/core_ext/string/strip.rb +3 -6
- data/lib/active_support/core_ext/struct.rb +3 -6
- data/lib/active_support/core_ext/time.rb +0 -2
- data/lib/active_support/core_ext/time/calculations.rb +18 -16
- data/lib/active_support/core_ext/time/conversions.rb +4 -2
- data/lib/active_support/core_ext/time/marshal.rb +2 -29
- data/lib/active_support/core_ext/time/zones.rb +19 -3
- data/lib/active_support/core_ext/uri.rb +1 -3
- data/lib/active_support/dependencies.rb +79 -44
- data/lib/active_support/dependencies/interlock.rb +47 -0
- data/lib/active_support/deprecation/behaviors.rb +12 -0
- data/lib/active_support/deprecation/method_wrappers.rb +42 -16
- data/lib/active_support/deprecation/proxy_wrappers.rb +47 -24
- data/lib/active_support/deprecation/reporting.rb +13 -2
- data/lib/active_support/duration.rb +5 -8
- data/lib/active_support/evented_file_update_checker.rb +150 -0
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/gem_version.rb +5 -5
- data/lib/active_support/hash_with_indifferent_access.rb +15 -17
- data/lib/active_support/i18n_railtie.rb +25 -4
- data/lib/active_support/inflector/inflections.rb +36 -5
- data/lib/active_support/inflector/methods.rb +87 -89
- data/lib/active_support/inflector/transliterate.rb +36 -21
- data/lib/active_support/json/decoding.rb +2 -8
- data/lib/active_support/json/encoding.rb +0 -50
- data/lib/active_support/key_generator.rb +4 -4
- data/lib/active_support/log_subscriber.rb +1 -1
- data/lib/active_support/log_subscriber/test_helper.rb +3 -3
- data/lib/active_support/logger.rb +4 -52
- data/lib/active_support/logger_silence.rb +3 -5
- data/lib/active_support/message_encryptor.rb +4 -11
- data/lib/active_support/message_verifier.rb +64 -8
- data/lib/active_support/multibyte/chars.rb +12 -3
- data/lib/active_support/multibyte/unicode.rb +6 -8
- data/lib/active_support/notifications.rb +2 -2
- data/lib/active_support/notifications/fanout.rb +5 -5
- data/lib/active_support/notifications/instrumenter.rb +19 -2
- data/lib/active_support/number_helper.rb +21 -15
- data/lib/active_support/number_helper/number_to_currency_converter.rb +4 -4
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +7 -2
- data/lib/active_support/number_helper/number_to_human_converter.rb +6 -4
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +28 -25
- data/lib/active_support/ordered_options.rb +15 -1
- data/lib/active_support/per_thread_registry.rb +3 -0
- data/lib/active_support/rails.rb +2 -2
- data/lib/active_support/railtie.rb +6 -1
- data/lib/active_support/rescuable.rb +4 -4
- data/lib/active_support/security_utils.rb +0 -7
- data/lib/active_support/string_inquirer.rb +1 -1
- data/lib/active_support/subscriber.rb +5 -10
- data/lib/active_support/tagged_logging.rb +3 -1
- data/lib/active_support/test_case.rb +13 -25
- data/lib/active_support/testing/assertions.rb +15 -13
- data/lib/active_support/testing/autorun.rb +8 -1
- data/lib/active_support/testing/composite_filter.rb +54 -0
- data/lib/active_support/testing/deprecation.rb +9 -8
- data/lib/active_support/testing/file_fixtures.rb +34 -0
- data/lib/active_support/testing/isolation.rb +22 -8
- data/lib/active_support/testing/method_call_assertions.rb +41 -0
- data/lib/active_support/testing/stream.rb +42 -0
- data/lib/active_support/testing/time_helpers.rb +6 -6
- data/lib/active_support/time_with_zone.rb +135 -53
- data/lib/active_support/values/time_zone.rb +80 -46
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/xml_mini.rb +15 -30
- data/lib/active_support/xml_mini/jdom.rb +1 -1
- data/lib/active_support/xml_mini/libxml.rb +5 -3
- data/lib/active_support/xml_mini/libxmlsax.rb +4 -1
- data/lib/active_support/xml_mini/nokogiri.rb +5 -3
- data/lib/active_support/xml_mini/nokogirisax.rb +3 -1
- data/lib/active_support/xml_mini/rexml.rb +3 -1
- metadata +57 -21
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +0 -15
- data/lib/active_support/core_ext/date_time/compatibility.rb +0 -16
- data/lib/active_support/core_ext/object/itself.rb +0 -15
- data/lib/active_support/core_ext/thread.rb +0 -86
- data/lib/active_support/core_ext/time/compatibility.rb +0 -14
- data/lib/active_support/logger_thread_safe_level.rb +0 -32
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
require 'active_support/json'
|
3
2
|
require 'active_support/core_ext/string/access'
|
4
3
|
require 'active_support/core_ext/string/behavior'
|
@@ -87,9 +86,19 @@ module ActiveSupport #:nodoc:
|
|
87
86
|
end
|
88
87
|
|
89
88
|
# Works like <tt>String#slice!</tt>, but returns an instance of
|
90
|
-
# Chars, or nil if the string was not modified.
|
89
|
+
# Chars, or nil if the string was not modified. The string will not be
|
90
|
+
# modified if the range given is out of bounds
|
91
|
+
#
|
92
|
+
# string = 'Welcome'
|
93
|
+
# string.mb_chars.slice!(3) # => #<ActiveSupport::Multibyte::Chars:0x000000038109b8 @wrapped_string="c">
|
94
|
+
# string # => 'Welome'
|
95
|
+
# string.mb_chars.slice!(0..3) # => #<ActiveSupport::Multibyte::Chars:0x00000002eb80a0 @wrapped_string="Welo">
|
96
|
+
# string # => 'me'
|
91
97
|
def slice!(*args)
|
92
|
-
|
98
|
+
string_sliced = @wrapped_string.slice!(*args)
|
99
|
+
if string_sliced
|
100
|
+
chars(string_sliced)
|
101
|
+
end
|
93
102
|
end
|
94
103
|
|
95
104
|
# Reverses all characters in the string.
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
module ActiveSupport
|
3
2
|
module Multibyte
|
4
3
|
module Unicode
|
@@ -11,7 +10,7 @@ module ActiveSupport
|
|
11
10
|
NORMALIZATION_FORMS = [:c, :kc, :d, :kd]
|
12
11
|
|
13
12
|
# The Unicode version that is supported by the implementation
|
14
|
-
UNICODE_VERSION = '
|
13
|
+
UNICODE_VERSION = '8.0.0'
|
15
14
|
|
16
15
|
# The default normalization used for operations that require
|
17
16
|
# normalization. It can be set to any of the normalizations
|
@@ -58,7 +57,7 @@ module ActiveSupport
|
|
58
57
|
# Returns a regular expression pattern that matches the passed Unicode
|
59
58
|
# codepoints.
|
60
59
|
def self.codepoints_to_pattern(array_of_codepoints) #:nodoc:
|
61
|
-
array_of_codepoints.collect{ |e| [e].pack 'U*' }.join('|')
|
60
|
+
array_of_codepoints.collect{ |e| [e].pack 'U*'.freeze }.join('|'.freeze)
|
62
61
|
end
|
63
62
|
TRAILERS_PAT = /(#{codepoints_to_pattern(LEADERS_AND_TRAILERS)})+\Z/u
|
64
63
|
LEADERS_PAT = /\A(#{codepoints_to_pattern(LEADERS_AND_TRAILERS)})+/u
|
@@ -211,9 +210,8 @@ module ActiveSupport
|
|
211
210
|
codepoints
|
212
211
|
end
|
213
212
|
|
214
|
-
# Ruby >= 2.1 has String#scrub, which is faster than the workaround used for < 2.1.
|
215
213
|
# Rubinius' String#scrub, however, doesn't support ASCII-incompatible chars.
|
216
|
-
if
|
214
|
+
if !defined?(Rubinius)
|
217
215
|
# Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent
|
218
216
|
# resulting in a valid UTF-8 string.
|
219
217
|
#
|
@@ -258,7 +256,7 @@ module ActiveSupport
|
|
258
256
|
# * <tt>string</tt> - The string to perform normalization on.
|
259
257
|
# * <tt>form</tt> - The form you want to normalize in. Should be one of
|
260
258
|
# the following: <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>.
|
261
|
-
# Default is ActiveSupport::Multibyte.default_normalization_form.
|
259
|
+
# Default is ActiveSupport::Multibyte::Unicode.default_normalization_form.
|
262
260
|
def normalize(string, form=nil)
|
263
261
|
form ||= @default_normalization_form
|
264
262
|
# See http://www.unicode.org/reports/tr15, Table 1
|
@@ -274,7 +272,7 @@ module ActiveSupport
|
|
274
272
|
compose(reorder_characters(decompose(:compatibility, codepoints)))
|
275
273
|
else
|
276
274
|
raise ArgumentError, "#{form} is not a valid normalization variant", caller
|
277
|
-
end.pack('U*')
|
275
|
+
end.pack('U*'.freeze)
|
278
276
|
end
|
279
277
|
|
280
278
|
def downcase(string)
|
@@ -339,7 +337,7 @@ module ActiveSupport
|
|
339
337
|
end
|
340
338
|
|
341
339
|
# Redefine the === method so we can write shorter rules for grapheme cluster breaks
|
342
|
-
@boundary.
|
340
|
+
@boundary.each_key do |k|
|
343
341
|
@boundary[k].instance_eval do
|
344
342
|
def ===(other)
|
345
343
|
detect { |i| i === other } ? true : false
|
@@ -69,8 +69,8 @@ module ActiveSupport
|
|
69
69
|
# is able to take the arguments as they come and provide an object-oriented
|
70
70
|
# interface to that data.
|
71
71
|
#
|
72
|
-
# It is also possible to pass an object
|
73
|
-
# <tt>subscribe</tt> method instead of a block:
|
72
|
+
# It is also possible to pass an object which responds to <tt>call</tt> method
|
73
|
+
# as the second parameter to the <tt>subscribe</tt> method instead of a block:
|
74
74
|
#
|
75
75
|
# module ActionController
|
76
76
|
# class PageRequest
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'mutex_m'
|
2
|
-
require '
|
2
|
+
require 'concurrent/map'
|
3
3
|
|
4
4
|
module ActiveSupport
|
5
5
|
module Notifications
|
@@ -12,7 +12,7 @@ module ActiveSupport
|
|
12
12
|
|
13
13
|
def initialize
|
14
14
|
@subscribers = []
|
15
|
-
@listeners_for =
|
15
|
+
@listeners_for = Concurrent::Map.new
|
16
16
|
super
|
17
17
|
end
|
18
18
|
|
@@ -42,8 +42,8 @@ module ActiveSupport
|
|
42
42
|
listeners_for(name).each { |s| s.start(name, id, payload) }
|
43
43
|
end
|
44
44
|
|
45
|
-
def finish(name, id, payload)
|
46
|
-
|
45
|
+
def finish(name, id, payload, listeners = listeners_for(name))
|
46
|
+
listeners.each { |s| s.finish(name, id, payload) }
|
47
47
|
end
|
48
48
|
|
49
49
|
def publish(name, *args)
|
@@ -51,7 +51,7 @@ module ActiveSupport
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def listeners_for(name)
|
54
|
-
# this is correctly done double-checked locking (
|
54
|
+
# this is correctly done double-checked locking (Concurrent::Map's lookups have volatile semantics)
|
55
55
|
@listeners_for[name] || synchronize do
|
56
56
|
# use synchronisation when accessing @subscribers
|
57
57
|
@listeners_for[name] ||= @subscribers.select { |s| s.subscribed_to?(name) }
|
@@ -15,14 +15,15 @@ module ActiveSupport
|
|
15
15
|
# and publish it. Notice that events get sent even if an error occurs
|
16
16
|
# in the passed-in block.
|
17
17
|
def instrument(name, payload={})
|
18
|
-
|
18
|
+
# some of the listeners might have state
|
19
|
+
listeners_state = start name, payload
|
19
20
|
begin
|
20
21
|
yield payload
|
21
22
|
rescue Exception => e
|
22
23
|
payload[:exception] = [e.class.name, e.message]
|
23
24
|
raise e
|
24
25
|
ensure
|
25
|
-
|
26
|
+
finish_with_state listeners_state, name, payload
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
@@ -36,6 +37,10 @@ module ActiveSupport
|
|
36
37
|
@notifier.finish name, @id, payload
|
37
38
|
end
|
38
39
|
|
40
|
+
def finish_with_state(listeners_state, name, payload)
|
41
|
+
@notifier.finish name, @id, payload, listeners_state
|
42
|
+
end
|
43
|
+
|
39
44
|
private
|
40
45
|
|
41
46
|
def unique_id
|
@@ -57,6 +62,18 @@ module ActiveSupport
|
|
57
62
|
@duration = nil
|
58
63
|
end
|
59
64
|
|
65
|
+
# Returns the difference in milliseconds between when the execution of the
|
66
|
+
# event started and when it ended.
|
67
|
+
#
|
68
|
+
# ActiveSupport::Notifications.subscribe('wait') do |*args|
|
69
|
+
# @event = ActiveSupport::Notifications::Event.new(*args)
|
70
|
+
# end
|
71
|
+
#
|
72
|
+
# ActiveSupport::Notifications.instrument('wait') do
|
73
|
+
# sleep 1
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# @event.duration # => 1000.138
|
60
77
|
def duration
|
61
78
|
@duration ||= 1000.0 * (self.end - time)
|
62
79
|
end
|
@@ -94,9 +94,9 @@ module ActiveSupport
|
|
94
94
|
# * <tt>:locale</tt> - Sets the locale to be used for formatting
|
95
95
|
# (defaults to current locale).
|
96
96
|
# * <tt>:precision</tt> - Sets the precision of the number
|
97
|
-
# (defaults to 3).
|
98
|
-
# * <tt>:significant</tt> - If +true+, precision will be the
|
99
|
-
# of significant_digits. If +false+, the
|
97
|
+
# (defaults to 3). Keeps the number's precision if nil.
|
98
|
+
# * <tt>:significant</tt> - If +true+, precision will be the number
|
99
|
+
# of significant_digits. If +false+, the number of fractional
|
100
100
|
# digits (defaults to +false+).
|
101
101
|
# * <tt>:separator</tt> - Sets the separator between the
|
102
102
|
# fractional and integer digits (defaults to ".").
|
@@ -115,9 +115,10 @@ module ActiveSupport
|
|
115
115
|
# number_to_percentage(100, precision: 0) # => 100%
|
116
116
|
# number_to_percentage(1000, delimiter: '.', separator: ',') # => 1.000,000%
|
117
117
|
# number_to_percentage(302.24398923423, precision: 5) # => 302.24399%
|
118
|
-
# number_to_percentage(1000, locale: :fr) # =>
|
118
|
+
# number_to_percentage(1000, locale: :fr) # => 1000,000%
|
119
|
+
# number_to_percentage(1000, precision: nil) # => 1000%
|
119
120
|
# number_to_percentage('98a') # => 98a%
|
120
|
-
# number_to_percentage(100, format: '%n %') # => 100 %
|
121
|
+
# number_to_percentage(100, format: '%n %') # => 100.000 %
|
121
122
|
def number_to_percentage(number, options = {})
|
122
123
|
NumberToPercentageConverter.convert(number, options)
|
123
124
|
end
|
@@ -134,6 +135,9 @@ module ActiveSupport
|
|
134
135
|
# to ",").
|
135
136
|
# * <tt>:separator</tt> - Sets the separator between the
|
136
137
|
# fractional and integer digits (defaults to ".").
|
138
|
+
# * <tt>:delimiter_pattern</tt> - Sets a custom regular expression used for
|
139
|
+
# deriving the placement of delimiter. Helpful when using currency formats
|
140
|
+
# like INR.
|
137
141
|
#
|
138
142
|
# ==== Examples
|
139
143
|
#
|
@@ -146,7 +150,10 @@ module ActiveSupport
|
|
146
150
|
# number_to_delimited(12345678.05, locale: :fr) # => 12 345 678,05
|
147
151
|
# number_to_delimited('112a') # => 112a
|
148
152
|
# number_to_delimited(98765432.98, delimiter: ' ', separator: ',')
|
149
|
-
#
|
153
|
+
# # => 98 765 432,98
|
154
|
+
# number_to_delimited("123456.78",
|
155
|
+
# delimiter_pattern: /(\d+?)(?=(\d\d)+(\d)(?!\d))/)
|
156
|
+
# # => 1,23,456.78
|
150
157
|
def number_to_delimited(number, options = {})
|
151
158
|
NumberToDelimitedConverter.convert(number, options)
|
152
159
|
end
|
@@ -161,9 +168,9 @@ module ActiveSupport
|
|
161
168
|
# * <tt>:locale</tt> - Sets the locale to be used for formatting
|
162
169
|
# (defaults to current locale).
|
163
170
|
# * <tt>:precision</tt> - Sets the precision of the number
|
164
|
-
# (defaults to 3).
|
165
|
-
# * <tt>:significant</tt> - If +true+, precision will be the
|
166
|
-
# of significant_digits. If +false+, the
|
171
|
+
# (defaults to 3). Keeps the number's precision if nil.
|
172
|
+
# * <tt>:significant</tt> - If +true+, precision will be the number
|
173
|
+
# of significant_digits. If +false+, the number of fractional
|
167
174
|
# digits (defaults to +false+).
|
168
175
|
# * <tt>:separator</tt> - Sets the separator between the
|
169
176
|
# fractional and integer digits (defaults to ".").
|
@@ -182,6 +189,7 @@ module ActiveSupport
|
|
182
189
|
# number_to_rounded(111.2345, significant: true) # => 111
|
183
190
|
# number_to_rounded(111.2345, precision: 1, significant: true) # => 100
|
184
191
|
# number_to_rounded(13, precision: 5, significant: true) # => 13.000
|
192
|
+
# number_to_rounded(13, precision: nil) # => 13
|
185
193
|
# number_to_rounded(111.234, locale: :fr) # => 111,234
|
186
194
|
#
|
187
195
|
# number_to_rounded(13, precision: 5, significant: true, strip_insignificant_zeros: true)
|
@@ -208,8 +216,8 @@ module ActiveSupport
|
|
208
216
|
# (defaults to current locale).
|
209
217
|
# * <tt>:precision</tt> - Sets the precision of the number
|
210
218
|
# (defaults to 3).
|
211
|
-
# * <tt>:significant</tt> - If +true+, precision will be the
|
212
|
-
# of significant_digits. If +false+, the
|
219
|
+
# * <tt>:significant</tt> - If +true+, precision will be the number
|
220
|
+
# of significant_digits. If +false+, the number of fractional
|
213
221
|
# digits (defaults to +true+)
|
214
222
|
# * <tt>:separator</tt> - Sets the separator between the
|
215
223
|
# fractional and integer digits (defaults to ".").
|
@@ -218,8 +226,6 @@ module ActiveSupport
|
|
218
226
|
# * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
|
219
227
|
# insignificant zeros after the decimal separator (defaults to
|
220
228
|
# +true+)
|
221
|
-
# * <tt>:prefix</tt> - If +:si+ formats the number using the SI
|
222
|
-
# prefix (defaults to :binary)
|
223
229
|
#
|
224
230
|
# ==== Examples
|
225
231
|
#
|
@@ -258,8 +264,8 @@ module ActiveSupport
|
|
258
264
|
# (defaults to current locale).
|
259
265
|
# * <tt>:precision</tt> - Sets the precision of the number
|
260
266
|
# (defaults to 3).
|
261
|
-
# * <tt>:significant</tt> - If +true+, precision will be the
|
262
|
-
# of significant_digits. If +false+, the
|
267
|
+
# * <tt>:significant</tt> - If +true+, precision will be the number
|
268
|
+
# of significant_digits. If +false+, the number of fractional
|
263
269
|
# digits (defaults to +true+)
|
264
270
|
# * <tt>:separator</tt> - Sets the separator between the
|
265
271
|
# fractional and integer digits (defaults to ".").
|
@@ -13,7 +13,7 @@ module ActiveSupport
|
|
13
13
|
end
|
14
14
|
|
15
15
|
rounded_number = NumberToRoundedConverter.convert(number, options)
|
16
|
-
format.gsub(
|
16
|
+
format.gsub('%n'.freeze, rounded_number).gsub('%u'.freeze, options[:unit])
|
17
17
|
end
|
18
18
|
|
19
19
|
private
|
@@ -23,20 +23,20 @@ module ActiveSupport
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def absolute_value(number)
|
26
|
-
number.respond_to?(
|
26
|
+
number.respond_to?(:abs) ? number.abs : number.sub(/\A-/, '')
|
27
27
|
end
|
28
28
|
|
29
29
|
def options
|
30
30
|
@options ||= begin
|
31
31
|
defaults = default_format_options.merge(i18n_opts)
|
32
|
-
# Override negative format if format options
|
32
|
+
# Override negative format if format options are given
|
33
33
|
defaults[:negative_format] = "-#{opts[:format]}" if opts[:format]
|
34
34
|
defaults.merge!(opts)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
def i18n_opts
|
39
|
-
# Set International negative format if not
|
39
|
+
# Set International negative format if it does not exist
|
40
40
|
i18n = i18n_format_options
|
41
41
|
i18n[:negative_format] ||= "-#{i18n[:format]}" if i18n[:format]
|
42
42
|
i18n
|
@@ -3,7 +3,7 @@ module ActiveSupport
|
|
3
3
|
class NumberToDelimitedConverter < NumberConverter #:nodoc:
|
4
4
|
self.validate_float = true
|
5
5
|
|
6
|
-
|
6
|
+
DEFAULT_DELIMITER_REGEX = /(\d)(?=(\d\d\d)+(?!\d))/
|
7
7
|
|
8
8
|
def convert
|
9
9
|
parts.join(options[:separator])
|
@@ -13,11 +13,16 @@ module ActiveSupport
|
|
13
13
|
|
14
14
|
def parts
|
15
15
|
left, right = number.to_s.split('.')
|
16
|
-
left.gsub!(
|
16
|
+
left.gsub!(delimiter_pattern) do |digit_to_delimit|
|
17
17
|
"#{digit_to_delimit}#{options[:delimiter]}"
|
18
18
|
end
|
19
19
|
[left, right].compact
|
20
20
|
end
|
21
|
+
|
22
|
+
def delimiter_pattern
|
23
|
+
options.fetch(:delimiter_pattern, DEFAULT_DELIMITER_REGEX)
|
24
|
+
end
|
25
|
+
|
21
26
|
end
|
22
27
|
end
|
23
28
|
end
|
@@ -20,10 +20,12 @@ module ActiveSupport
|
|
20
20
|
exponent = calculate_exponent(units)
|
21
21
|
@number = number / (10 ** exponent)
|
22
22
|
|
23
|
+
until (rounded_number = NumberToRoundedConverter.convert(number, options)) != NumberToRoundedConverter.convert(1000, options)
|
24
|
+
@number = number / 1000.0
|
25
|
+
exponent += 3
|
26
|
+
end
|
23
27
|
unit = determine_unit(units, exponent)
|
24
|
-
|
25
|
-
rounded_number = NumberToRoundedConverter.convert(number, options)
|
26
|
-
format.gsub(/%n/, rounded_number).gsub(/%u/, unit).strip
|
28
|
+
format.gsub('%n'.freeze, rounded_number).gsub('%u'.freeze, unit).strip
|
27
29
|
end
|
28
30
|
|
29
31
|
private
|
@@ -59,7 +61,7 @@ module ActiveSupport
|
|
59
61
|
translate_in_locale("human.decimal_units.units", raise: true)
|
60
62
|
else
|
61
63
|
raise ArgumentError, ":units must be a Hash or String translation scope."
|
62
|
-
end.keys.map { |e_name| INVERTED_DECIMAL_UNITS[e_name] }.sort_by
|
64
|
+
end.keys.map { |e_name| INVERTED_DECIMAL_UNITS[e_name] }.sort_by(&:-@)
|
63
65
|
end
|
64
66
|
end
|
65
67
|
end
|
@@ -7,6 +7,10 @@ module ActiveSupport
|
|
7
7
|
self.validate_float = true
|
8
8
|
|
9
9
|
def convert
|
10
|
+
if opts.key?(:prefix)
|
11
|
+
ActiveSupport::Deprecation.warn('The :prefix option of `number_to_human_size` is deprecated and will be removed in Rails 5.1 with no replacement.')
|
12
|
+
end
|
13
|
+
|
10
14
|
@number = Float(number)
|
11
15
|
|
12
16
|
# for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
|
@@ -20,7 +24,7 @@ module ActiveSupport
|
|
20
24
|
human_size = number / (base ** exponent)
|
21
25
|
number_to_format = NumberToRoundedConverter.convert(human_size, options)
|
22
26
|
end
|
23
|
-
conversion_format.gsub(
|
27
|
+
conversion_format.gsub('%n'.freeze, number_to_format).gsub('%u'.freeze, unit)
|
24
28
|
end
|
25
29
|
|
26
30
|
private
|
@@ -6,36 +6,39 @@ module ActiveSupport
|
|
6
6
|
|
7
7
|
def convert
|
8
8
|
precision = options.delete :precision
|
9
|
-
significant = options.delete :significant
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
if significant && precision > 0
|
21
|
-
digits, rounded_number = digits_and_rounded_number(precision)
|
22
|
-
precision -= digits
|
23
|
-
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
|
-
end
|
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
|
29
19
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
a + '.' + b[0, precision]
|
20
|
+
if options.delete(:significant) && precision > 0
|
21
|
+
digits, rounded_number = digits_and_rounded_number(precision)
|
22
|
+
precision -= digits
|
23
|
+
precision = 0 if precision < 0 # don't let it be negative
|
35
24
|
else
|
36
|
-
|
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
|
37
28
|
end
|
38
29
|
|
30
|
+
formatted_string =
|
31
|
+
if BigDecimal === rounded_number && rounded_number.finite?
|
32
|
+
s = rounded_number.to_s('F') + '0'*precision
|
33
|
+
a, b = s.split('.', 2)
|
34
|
+
a + '.' + b[0, precision]
|
35
|
+
else
|
36
|
+
"%00.#{precision}f" % rounded_number
|
37
|
+
end
|
38
|
+
else
|
39
|
+
formatted_string = number
|
40
|
+
end
|
41
|
+
|
39
42
|
delimited_number = NumberToDelimitedConverter.convert(formatted_string, options)
|
40
43
|
format_number(delimited_number)
|
41
44
|
end
|