diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb
index d8fffe75edc33..854fabd21f8ad 100644
--- a/actionpack/test/template/number_helper_test.rb
+++ b/actionpack/test/template/number_helper_test.rb
@@ -179,13 +179,24 @@ def test_number_to_human_size_with_si_prefix
assert_equal '3 Bytes', number_to_human_size(3.14159265, :prefix => :si)
assert_equal '123 Bytes', number_to_human_size(123.0, :prefix => :si)
assert_equal '123 Bytes', number_to_human_size(123, :prefix => :si)
- assert_equal '1.23 KB', number_to_human_size(1234, :prefix => :si)
- assert_equal '12.3 KB', number_to_human_size(12345, :prefix => :si)
+ assert_equal '1.23 kB', number_to_human_size(1234, prefix: :si)
+ assert_equal '12.3 kB', number_to_human_size(12345, prefix: :si)
assert_equal '1.23 MB', number_to_human_size(1234567, :prefix => :si)
assert_equal '1.23 GB', number_to_human_size(1234567890, :prefix => :si)
assert_equal '1.23 TB', number_to_human_size(1234567890123, :prefix => :si)
end
+ def test_number_to_human_size_with_iso_prefix
+ assert_equal '3 Bytes', number_to_human_size(3.14159265, prefix: :iso)
+ assert_equal '123 Bytes', number_to_human_size(123.0, prefix: :iso)
+ assert_equal '123 Bytes', number_to_human_size(123, prefix: :iso)
+ assert_equal '1.21 KiB', number_to_human_size(1234, prefix: :iso)
+ assert_equal '12.1 KiB', number_to_human_size(12345, prefix: :iso)
+ assert_equal '1.18 MiB', number_to_human_size(1234567, prefix: :iso)
+ assert_equal '1.15 GiB', number_to_human_size(1234567890, prefix: :iso)
+ assert_equal '1.12 TiB', number_to_human_size(1234567890123, prefix: :iso)
+ end
+
def test_number_to_human_size_with_options_hash
assert_equal '1.2 MB', number_to_human_size(1234567, :precision => 2)
assert_equal '3 Bytes', number_to_human_size(3.14159265, :precision => 4)
diff --git a/activesupport/lib/active_support/locale/en.yml b/activesupport/lib/active_support/locale/en.yml
index f4900dc9359a1..979c55db07de4 100644
--- a/activesupport/lib/active_support/locale/en.yml
+++ b/activesupport/lib/active_support/locale/en.yml
@@ -106,6 +106,22 @@ en:
mb: "MB"
gb: "GB"
tb: "TB"
+ si_units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "kB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
+ iso_units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KiB"
+ mb: "MiB"
+ gb: "GiB"
+ tb: "TiB"
# Used in NumberHelper.number_to_human()
decimal_units:
format: "%n %u"
diff --git a/activesupport/lib/active_support/number_helper.rb b/activesupport/lib/active_support/number_helper.rb
index 2191471daac23..afc4c76cc2af7 100644
--- a/activesupport/lib/active_support/number_helper.rb
+++ b/activesupport/lib/active_support/number_helper.rb
@@ -4,9 +4,19 @@
require 'active_support/i18n'
module ActiveSupport
+ class << self
+ delegate :default_size_prefix, :default_size_prefix=,
+ to: :'ActiveSupport::NumberHelper'
+ end
+
module NumberHelper
extend self
+ class << self
+ attr_accessor :default_size_prefix
+ end
+ self.default_size_prefix = :customary
+
DEFAULTS = {
# Used in number_to_delimited
# These are also the defaults for 'currency', 'percentage', 'precision', and 'human'
@@ -74,6 +84,20 @@ module NumberHelper
mb: "MB",
gb: "GB",
tb: "TB"
+ },
+ iso_units: {
+ byte: "Bytes",
+ kb: "KiB",
+ mb: "MiB",
+ gb: "GiB",
+ tb: "TiB"
+ },
+ si_units: {
+ byte: "Bytes",
+ kb: "kB",
+ mb: "MB",
+ gb: "GB",
+ tb: "TB"
}
},
# Used in number_to_human
@@ -398,8 +422,12 @@ def number_to_rounded(number, options = {})
# * :strip_insignificant_zeros - If +true+ removes
# insignificant zeros after the decimal separator (defaults to
# +true+)
- # * :prefix - If +:si+ formats the number using the SI
- # prefix (defaults to :binary)
+ # * :prefix - If +:si+ formats the number using SI
+ # prefixes. If +:iec+ or +:iso+ formats the numbers using
+ # ISO/IEC 80000 binary prefixes. If +:customary+ formats the
+ # number to customary binary prefixes. Defaults to
+ # +ActiveSupport.default_size_prefix+, which is +:customary+,
+ # but can be set to one of the others.
#
# ==== Examples
#
@@ -432,10 +460,23 @@ def number_to_human_size(number, options = {})
storage_units_format = translate_number_value_with_default('human.storage_units.format', :locale => options[:locale], :raise => true)
- base = options[:prefix] == :si ? 1000 : 1024
+ options[:prefix] ||= ActiveSupport.default_size_prefix
+ case options[:prefix]
+ when :si
+ base = 1000
+ system_key = "si_units"
+ when :iec, :iso
+ base = 1024
+ system_key = "iso_units"
+ when :customary
+ base = 1024
+ system_key = "units"
+ else
+ raise ArgumentError, ":prefix must be :customary, :si, :iec, or :iso"
+ end
if number.to_i < base
- unit = translate_number_value_with_default('human.storage_units.units.byte', :locale => options[:locale], :count => number.to_i, :raise => true)
+ unit = translate_number_value_with_default("human.storage_units.#{system_key}.byte", locale: options[:locale], count: number.to_i, raise: true)
storage_units_format.gsub(/%n/, number.to_i.to_s).gsub(/%u/, unit)
else
max_exp = STORAGE_UNITS.size - 1
@@ -444,7 +485,7 @@ def number_to_human_size(number, options = {})
number /= base ** exponent
unit_key = STORAGE_UNITS[exponent]
- unit = translate_number_value_with_default("human.storage_units.units.#{unit_key}", :locale => options[:locale], :count => number, :raise => true)
+ unit = translate_number_value_with_default("human.storage_units.#{system_key}.#{unit_key}", locale: options[:locale], count: number, raise: true)
formatted_number = self.number_to_rounded(number, options)
storage_units_format.gsub(/%n/, formatted_number).gsub(/%u/, unit)
diff --git a/activesupport/test/core_ext/numeric_ext_test.rb b/activesupport/test/core_ext/numeric_ext_test.rb
index 435f4aa5a14b3..d5935a353dc44 100644
--- a/activesupport/test/core_ext/numeric_ext_test.rb
+++ b/activesupport/test/core_ext/numeric_ext_test.rb
@@ -344,13 +344,24 @@ def test_to_s__human_size_with_si_prefix
assert_equal '3 Bytes', 3.14159265.to_s(:human_size, :prefix => :si)
assert_equal '123 Bytes', 123.0.to_s(:human_size, :prefix => :si)
assert_equal '123 Bytes', 123.to_s(:human_size, :prefix => :si)
- assert_equal '1.23 KB', 1234.to_s(:human_size, :prefix => :si)
- assert_equal '12.3 KB', 12345.to_s(:human_size, :prefix => :si)
+ assert_equal '1.23 kB', 1234.to_s(:human_size, prefix: :si)
+ assert_equal '12.3 kB', 12345.to_s(:human_size, prefix: :si)
assert_equal '1.23 MB', 1234567.to_s(:human_size, :prefix => :si)
assert_equal '1.23 GB', 1234567890.to_s(:human_size, :prefix => :si)
assert_equal '1.23 TB', 1234567890123.to_s(:human_size, :prefix => :si)
end
+ def test_to_s__human_size_with_iso_prefix
+ assert_equal '3 Bytes', 3.14159265.to_s(:human_size, prefix: :iso)
+ assert_equal '123 Bytes', 123.0.to_s(:human_size, prefix: :iso)
+ assert_equal '123 Bytes', 123.to_s(:human_size, prefix: :iso)
+ assert_equal '1.21 KiB', 1234.to_s(:human_size, prefix: :iso)
+ assert_equal '12.1 KiB', 12345.to_s(:human_size, prefix: :iso)
+ assert_equal '1.18 MiB', 1234567.to_s(:human_size, prefix: :iso)
+ assert_equal '1.15 GiB', 1234567890.to_s(:human_size, prefix: :iso)
+ assert_equal '1.12 TiB', 1234567890123.to_s(:human_size, prefix: :iso)
+ end
+
def test_to_s__human_size_with_options_hash
assert_equal '1.2 MB', 1234567.to_s(:human_size, :precision => 2)
assert_equal '3 Bytes', 3.14159265.to_s(:human_size, :precision => 4)
diff --git a/activesupport/test/number_helper_test.rb b/activesupport/test/number_helper_test.rb
index 5f54587f93ff6..f309dc1a81e9e 100644
--- a/activesupport/test/number_helper_test.rb
+++ b/activesupport/test/number_helper_test.rb
@@ -209,14 +209,51 @@ def test_number_to_human_size_with_si_prefix
assert_equal '3 Bytes', number_helper.number_to_human_size(3.14159265, :prefix => :si)
assert_equal '123 Bytes', number_helper.number_to_human_size(123.0, :prefix => :si)
assert_equal '123 Bytes', number_helper.number_to_human_size(123, :prefix => :si)
- assert_equal '1.23 KB', number_helper.number_to_human_size(1234, :prefix => :si)
- assert_equal '12.3 KB', number_helper.number_to_human_size(12345, :prefix => :si)
+ assert_equal '1.23 kB', number_helper.number_to_human_size(1234, prefix: :si)
+ assert_equal '12.3 kB', number_helper.number_to_human_size(12345, prefix: :si)
assert_equal '1.23 MB', number_helper.number_to_human_size(1234567, :prefix => :si)
assert_equal '1.23 GB', number_helper.number_to_human_size(1234567890, :prefix => :si)
assert_equal '1.23 TB', number_helper.number_to_human_size(1234567890123, :prefix => :si)
end
end
+ def test_number_to_human_size_with_iso_prefix
+ [:iec, :iso].each do |prefix|
+ [@instance_with_helpers, TestClassWithClassNumberHelpers, ActiveSupport::NumberHelper].each do |number_helper|
+ assert_equal '3 Bytes', number_helper.number_to_human_size(3.14159265, prefix: prefix)
+ assert_equal '123 Bytes', number_helper.number_to_human_size(123.0, prefix: prefix)
+ assert_equal '123 Bytes', number_helper.number_to_human_size(123, prefix: prefix)
+ assert_equal '1.21 KiB', number_helper.number_to_human_size(1234, prefix: prefix)
+ assert_equal '12.1 KiB', number_helper.number_to_human_size(12345, prefix: prefix)
+ assert_equal '1.18 MiB', number_helper.number_to_human_size(1234567, prefix: prefix)
+ assert_equal '1.15 GiB', number_helper.number_to_human_size(1234567890, prefix: prefix)
+ assert_equal '1.12 TiB', number_helper.number_to_human_size(1234567890123, prefix: prefix)
+ end
+ end
+ end
+
+ def test_number_to_human_size_using_active_support_default_size_prefix
+ begin
+ ActiveSupport.default_size_prefix = :iso
+ [@instance_with_helpers, TestClassWithClassNumberHelpers, ActiveSupport::NumberHelper].each do |number_helper|
+ assert_equal '1.12 TiB', number_helper.number_to_human_size(1234567890123)
+ end
+ [@instance_with_helpers, TestClassWithClassNumberHelpers, ActiveSupport::NumberHelper].each do |number_helper|
+ assert_equal '1.12 TB', number_helper.number_to_human_size(1234567890123, prefix: :customary)
+ end
+ ensure
+ ActiveSupport.default_size_prefix = :customary
+ end
+ end
+
+ def test_number_to_human_size_with_invalid_prefix
+ [@instance_with_helpers, TestClassWithClassNumberHelpers, ActiveSupport::NumberHelper].each do |number_helper|
+ assert_raise ArgumentError do
+ number_helper.number_to_human_size(1, prefix: :unknown_prefix)
+ end
+ end
+ end
+
def test_number_to_human_size_with_options_hash
[@instance_with_helpers, TestClassWithClassNumberHelpers, ActiveSupport::NumberHelper].each do |number_helper|
assert_equal '1.2 MB', number_helper.number_to_human_size(1234567, :precision => 2)