quality_extensions 1.1.6 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +4 -0
  3. data/License +403 -0
  4. data/Rakefile +2 -0
  5. data/Readme.rdoc +2 -3
  6. data/VERSION +1 -0
  7. data/doc_include/ReleaseNotes-0.0.10 +1 -0
  8. data/doc_include/ReleaseNotes-0.0.12 +1 -0
  9. data/doc_include/ReleaseNotes-0.0.13 +2 -0
  10. data/doc_include/ReleaseNotes-0.0.14 +1 -0
  11. data/doc_include/ReleaseNotes-0.0.15 +2 -0
  12. data/doc_include/ReleaseNotes-0.0.16 +1 -0
  13. data/doc_include/ReleaseNotes-0.0.17 +1 -0
  14. data/doc_include/ReleaseNotes-0.0.18 +1 -0
  15. data/doc_include/ReleaseNotes-0.0.19 +1 -0
  16. data/doc_include/ReleaseNotes-0.0.20 +1 -0
  17. data/doc_include/ReleaseNotes-0.0.21 +7 -0
  18. data/doc_include/ReleaseNotes-0.0.22 +2 -0
  19. data/doc_include/ReleaseNotes-0.0.23 +1 -0
  20. data/doc_include/ReleaseNotes-0.0.24 +3 -0
  21. data/doc_include/ReleaseNotes-0.0.25 +3 -0
  22. data/doc_include/ReleaseNotes-0.0.26 +2 -0
  23. data/doc_include/ReleaseNotes-0.0.27 +1 -0
  24. data/doc_include/ReleaseNotes-0.0.28 +1 -0
  25. data/doc_include/ReleaseNotes-0.0.29 +3 -0
  26. data/doc_include/ReleaseNotes-0.0.3 +1 -0
  27. data/doc_include/ReleaseNotes-0.0.30 +4 -0
  28. data/doc_include/ReleaseNotes-0.0.31 +1 -0
  29. data/doc_include/ReleaseNotes-0.0.32 +1 -0
  30. data/doc_include/ReleaseNotes-0.0.33 +1 -0
  31. data/doc_include/ReleaseNotes-0.0.34 +2 -0
  32. data/doc_include/ReleaseNotes-0.0.35 +1 -0
  33. data/doc_include/ReleaseNotes-0.0.36 +1 -0
  34. data/doc_include/ReleaseNotes-0.0.37 +1 -0
  35. data/doc_include/ReleaseNotes-0.0.38 +1 -0
  36. data/doc_include/ReleaseNotes-0.0.39 +1 -0
  37. data/doc_include/ReleaseNotes-0.0.4 +2 -0
  38. data/doc_include/ReleaseNotes-0.0.40 +1 -0
  39. data/doc_include/ReleaseNotes-0.0.41 +1 -0
  40. data/doc_include/ReleaseNotes-0.0.42 +2 -0
  41. data/doc_include/ReleaseNotes-0.0.43 +2 -0
  42. data/doc_include/ReleaseNotes-0.0.44 +3 -0
  43. data/doc_include/ReleaseNotes-0.0.45 +1 -0
  44. data/doc_include/ReleaseNotes-0.0.46 +1 -0
  45. data/doc_include/ReleaseNotes-0.0.47 +1 -0
  46. data/doc_include/ReleaseNotes-0.0.48 +2 -0
  47. data/doc_include/ReleaseNotes-0.0.49 +2 -0
  48. data/doc_include/ReleaseNotes-0.0.5 +1 -0
  49. data/doc_include/ReleaseNotes-0.0.50 +1 -0
  50. data/doc_include/ReleaseNotes-0.0.51 +1 -0
  51. data/doc_include/ReleaseNotes-0.0.52 +1 -0
  52. data/doc_include/ReleaseNotes-0.0.53 +3 -0
  53. data/doc_include/ReleaseNotes-0.0.54 +1 -0
  54. data/doc_include/ReleaseNotes-0.0.55 +2 -0
  55. data/doc_include/ReleaseNotes-0.0.56 +1 -0
  56. data/doc_include/ReleaseNotes-0.0.57 +3 -0
  57. data/doc_include/ReleaseNotes-0.0.58 +1 -0
  58. data/doc_include/ReleaseNotes-0.0.59 +1 -0
  59. data/doc_include/ReleaseNotes-0.0.6 +3 -0
  60. data/doc_include/ReleaseNotes-0.0.60 +3 -0
  61. data/doc_include/ReleaseNotes-0.0.61 +1 -0
  62. data/doc_include/ReleaseNotes-0.0.62 +1 -0
  63. data/doc_include/ReleaseNotes-0.0.63 +1 -0
  64. data/doc_include/ReleaseNotes-0.0.64 +1 -0
  65. data/doc_include/ReleaseNotes-0.0.7 +1 -0
  66. data/doc_include/ReleaseNotes-0.0.8 +2 -0
  67. data/doc_include/ReleaseNotes-0.0.9 +1 -0
  68. data/doc_include/ReleaseNotes-0.1.1 +1 -0
  69. data/doc_include/ReleaseNotes-0.1.2 +1 -0
  70. data/doc_include/ReleaseNotes-0.1.3 +1 -0
  71. data/doc_include/ReleaseNotes-0.1.4 +1 -0
  72. data/doc_include/ReleaseNotes-0.1.5 +0 -0
  73. data/doc_include/ReleaseNotes-1.0.0 +1 -0
  74. data/doc_include/ReleaseNotes-1.0.1 +1 -0
  75. data/doc_include/ReleaseNotes-1.0.2 +1 -0
  76. data/doc_include/ReleaseNotes-1.0.3 +1 -0
  77. data/doc_include/ReleaseNotes-1.1.0 +1 -0
  78. data/doc_include/ReleaseNotes-1.1.1 +1 -0
  79. data/doc_include/ReleaseNotes-1.1.6 +1 -0
  80. data/doc_include/assert_equal_with_difference_highlighting-there_he_is.png +0 -0
  81. data/doc_include/assert_equal_with_difference_highlighting-wheres_waldo.png +0 -0
  82. data/escape/Rakefile +62 -0
  83. data/escape/Readme +16 -0
  84. data/escape/doc_include/ReleaseNotes-0.0.1 +1 -0
  85. data/escape/doc_include/ReleaseNotes-0.0.3 +1 -0
  86. data/escape/doc_include/ReleaseNotes-0.0.4 +1 -0
  87. data/escape/doc_include/ReleaseNotes-0.0.5 +1 -0
  88. data/escape/doc_include/template/qualitysmith.rb +631 -0
  89. data/escape/lib/escape.rb +302 -0
  90. data/escape/pkg/escape-0.0.5.tgz +0 -0
  91. data/escape/pkg/escape-0.0.5.zip +0 -0
  92. data/escape/pkg/escape-0.0.5/Readme +16 -0
  93. data/escape/pkg/escape-0.0.5/doc_include/template/qualitysmith.rb +631 -0
  94. data/escape/pkg/escape-0.0.5/lib/escape.rb +302 -0
  95. data/lib/quality_extensions.rb +3 -1
  96. data/lib/quality_extensions/array/average.rb +45 -0
  97. data/lib/quality_extensions/array/expand_ranges.rb +2 -2
  98. data/lib/quality_extensions/array/shell_escape.rb +2 -2
  99. data/lib/quality_extensions/color/gradiate.rb +5 -5
  100. data/lib/quality_extensions/enumerable/every.rb +2 -2
  101. data/lib/quality_extensions/enumerable/grep_with_index.rb +51 -0
  102. data/lib/quality_extensions/enumerable/grepv.rb +1 -0
  103. data/lib/quality_extensions/enumerable/map_with_index.rb +2 -0
  104. data/lib/quality_extensions/enumerable/max_by_value.rb +72 -0
  105. data/lib/quality_extensions/enumerable/select_while.rb +7 -2
  106. data/lib/quality_extensions/enumerable/select_with_index.rb +2 -2
  107. data/lib/quality_extensions/float/truncate.rb +2 -1
  108. data/lib/quality_extensions/hash/except.rb +2 -2
  109. data/lib/quality_extensions/hash/to_query_string.rb +6 -6
  110. data/lib/quality_extensions/helpers/numbers.rb +259 -0
  111. data/lib/quality_extensions/kernel/die.rb +2 -2
  112. data/lib/quality_extensions/kernel/filter_output.rb +1 -0
  113. data/lib/quality_extensions/kernel/require_all.rb +7 -7
  114. data/lib/quality_extensions/module/guard_method.rb +3 -3
  115. data/lib/quality_extensions/object/non.rb +10 -4
  116. data/lib/quality_extensions/pathname.rb +51 -3
  117. data/lib/quality_extensions/regexp/named_captures.rb +7 -6
  118. data/lib/quality_extensions/regexp/to_plain_s.rb +116 -0
  119. data/lib/quality_extensions/safe_method.rb +100 -0
  120. data/lib/quality_extensions/safe_nil.rb +87 -11
  121. data/lib/quality_extensions/string/chomped_lines.rb +0 -0
  122. data/lib/quality_extensions/string/integer_eh.rb +2 -2
  123. data/lib/quality_extensions/string/prefix.rb +120 -0
  124. data/lib/quality_extensions/string/prefix_lines.rb +4 -69
  125. data/lib/quality_extensions/string/safe_numeric_conversion.rb +5 -5
  126. data/lib/quality_extensions/string/shell_escape.rb +3 -3
  127. data/lib/quality_extensions/string/to_proc.rb +119 -0
  128. data/lib/quality_extensions/template.rb +2 -2
  129. data/lib/quality_extensions/test/difference_highlighting.rb +2 -2
  130. data/lib/quality_extensions/version.rb +3 -0
  131. data/quality_extensions.gemspec +21 -0
  132. metadata +249 -145
  133. data/lib/Xfind_bug_test.rb +0 -28
@@ -0,0 +1 @@
1
+ str.lines.grepv(/#/) # all lines *not* beginnnig with #
@@ -4,6 +4,8 @@
4
4
  # License:: Ruby License
5
5
  # Submit to Facets?:: Yes. facets/enumerable/collect.rb only has non-in-place version (map_with_index).
6
6
  # Developer notes::
7
+ # * No longer needed in Ruby 1.9.1:
8
+ # a.to_enum(:map!).with_index
7
9
  # Changes::
8
10
  #++
9
11
 
@@ -0,0 +1,72 @@
1
+ #--
2
+ # Author:: Tyler Rick
3
+ # Copyright:: Copyright (c) 2010, Tyler Rick
4
+ # License:: Ruby License
5
+ # Submit to Facets?::
6
+ # Developer notes::
7
+ # History::
8
+ #++
9
+
10
+
11
+ module Enumerable
12
+
13
+ # Instead of returns the object in enum that gives the maximum value from the
14
+ # given block, like max_by does, returns the *maximum value* calculated by
15
+ # the given block (which is tested on each object in enum, just like in
16
+ # max_by).
17
+ #
18
+ # Notice the difference:
19
+ # ['a','abc','ab'].max_by {|el| el.length}.should == 'abc'
20
+ # ['a','abc','ab'].max_by_value {|el| el.length}.should == 3
21
+ #
22
+ def max_by_value(&block)
23
+ max_value = nil
24
+ each do |el|
25
+ value = yield el
26
+ if max_value.nil?
27
+ max_value = value
28
+ else
29
+ max_value = [value, max_value].max
30
+ end
31
+ end
32
+ max_value
33
+ end
34
+ end
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+ # _____ _
43
+ # |_ _|__ ___| |_
44
+ # | |/ _ \/ __| __|
45
+ # | | __/\__ \ |_
46
+ # |_|\___||___/\__|
47
+ #
48
+ =begin test
49
+ require 'spec/autorun'
50
+
51
+ describe 'Enumerable#max_by_value' do
52
+ it 'works in simple case' do
53
+ [1,3,2].max_by_value {|el| el}.should == 3
54
+ end
55
+
56
+ it 'works for array of strings' do
57
+ ['a','abc','ab'].max_by_value {|el| el.length}.should == 3
58
+ ['a','abc','ab'].max_by {|el| el.length}.should == 'abc'
59
+ end
60
+
61
+ it 'works in more complicated example' do
62
+ files = [
63
+ ["app/controllers/application_controller.rb.orig",
64
+ Pathname.new('app/controllers/application_controller.rb')]
65
+ ]
66
+ max = files.max_by {|a| a.first.to_s.length}.first.to_s.length
67
+ files.max_by_value {|a| a.first.to_s.length}.should == max
68
+
69
+ end
70
+ end
71
+ =end
72
+
@@ -9,8 +9,8 @@
9
9
  # * !! Why does Hash#each_with_index yield |(k,v), i| but my select_with_index yields flat |k, v, i| ?
10
10
  #++
11
11
 
12
- require 'facets/kernel/require_local'
13
- require_local 'select_with_index'
12
+ require 'facets/kernel/require_relative'
13
+ require_relative 'select_with_index'
14
14
 
15
15
  module Enumerable
16
16
  # Original version before I changed it to use select so that Hash#select_until would return a hash instead of an array.
@@ -43,12 +43,17 @@ module Enumerable
43
43
  # If +inclusive+ is false, only those elements occuring _before_ the first element for which +block+ is true will be returned.
44
44
  # If +inclusive+ is true (the default), those elements occuring up to and _including_ the first element for which +block+ is true will be returned.
45
45
  #
46
+ # Examples:
47
+ #
46
48
  # (0..3).select_until {|v| v == 1} # => [0, 1]
47
49
  # (0..3).select_until(false) {|v| v == 1} # => [0]
48
50
  #
49
51
  # {'a'=>1, 'b'=>2, 'c'=>3, 'd'=>1}.select_until {|k, v| v == 2} ) # => {"a"=>1, "b"=>2}
50
52
  # {'a'=>1, 'b'=>2, 'c'=>3, 'd'=>1}.select_until(false) {|k, v| v == 2} ) # => {"a"=>1}
51
53
  #
54
+ # puts caller # => 30 lines of context, many of them so far removed that they are irrelevant
55
+ # puts caller.select_until {|l| l =~ %r(/app/) } # only print the stack back to the first frame from our own code
56
+ #
52
57
  def select_until(inclusive = true)
53
58
  return self unless block_given?
54
59
 
@@ -8,8 +8,8 @@
8
8
  # History::
9
9
  #++
10
10
 
11
- require 'facets/kernel/require_local'
12
- require_local 'select_bang'
11
+ require 'facets/kernel/require_relative'
12
+ require_relative 'select_bang'
13
13
 
14
14
  module Enumerable
15
15
  # def reject!
@@ -32,11 +32,12 @@ require 'quality_extensions/module/alias_method_chain'
32
32
  # end
33
33
 
34
34
  class Float
35
+ # This is the same as round_at except instead of rounding (up or down) to the nearest integer, it always truncates, rounding down to the next lowest integer.
35
36
  def truncate_with_precision(d)
36
37
  (self * (10.0 ** d)).truncate_without_precision.to_f / (10.0 ** d)
37
38
  end
38
39
  alias_method_chain :truncate, :precision
39
- end
40
+ end
40
41
 
41
42
 
42
43
  # _____ _
@@ -1,3 +1,3 @@
1
1
  # Alias for:
2
- require 'facets/kernel/require_local'
3
- require_local 'only'
2
+ require 'facets/kernel/require_relative'
3
+ require_relative 'only'
@@ -8,8 +8,8 @@
8
8
  $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
9
9
  autoload :CGI, 'cgi'
10
10
  require 'rubygems'
11
- require 'facets/kernel/require_local'
12
- require_local '../array/to_query_string.rb'
11
+ require 'facets/kernel/require_relative'
12
+ require_relative '../array/to_query_string.rb'
13
13
 
14
14
  class Hash
15
15
 
@@ -86,7 +86,7 @@ class TheTest < Test::Unit::TestCase
86
86
  }
87
87
  }
88
88
  }
89
- assert_equal ['foo=bar', 'names[common]=smith', 'names[uncommon][first]=lance', 'names[uncommon][last]=wilheiminkauf'].to_set,
89
+ assert_equal ['foo=bar', 'names[common]=smith', 'names[uncommon][first]=lance', 'names[uncommon][last]=wilheiminkauf'].to_set,
90
90
  data.to_query_string.split(/&/).to_set
91
91
  end
92
92
  def test_hash_to_query_string_nesting_2
@@ -98,13 +98,13 @@ class TheTest < Test::Unit::TestCase
98
98
  ]
99
99
  }
100
100
  assert_equal 'names[common]=smith&names[uncommon][]=frankenwatzel&names[uncommon][]=wilheiminkauf', data.to_query_string('names')
101
- assert_equal( {'names' => data}.to_query_string(),
101
+ assert_equal( {'names' => data}.to_query_string(),
102
102
  data.to_query_string('names') )
103
103
  end
104
-
104
+
105
105
  def test_hash_to_query_string_encoding
106
106
  data = {'f&r' => 'a w$'}
107
-
107
+
108
108
  assert_equal 'f%26r=a+w%24', data.to_query_string
109
109
  end
110
110
  end
@@ -0,0 +1,259 @@
1
+ #--
2
+ # Author:: Tyler Rick
3
+ # Copyright:: Ruby on Rails developers
4
+ # License:: Ruby on Rails license
5
+ # Submit to Facets?:: yes
6
+ # Developer notes::
7
+ # History::
8
+ #++
9
+
10
+ require 'facets/hash/symbolize_keys'
11
+
12
+
13
+ class Array
14
+ def extract_options!
15
+ last.is_a?(::Hash) ? pop : {}
16
+ end
17
+ end
18
+
19
+ #-------------------------------------------------------------------------------
20
+
21
+ module Kernel
22
+ # TODO: use quality_extensions/helpers/numbers instead
23
+ # Adapted from /var/lib/gems/1.9.1/gems/actionpack-2.3.4/lib/action_view/helpers/number_helper.rb
24
+
25
+ # Formats a +number+ with grouped thousands using +delimiter+ (e.g., 12,324). You can
26
+ # customize the format in the +options+ hash.
27
+ #
28
+ # ==== Options
29
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ",").
30
+ # * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
31
+ #
32
+ # ==== Examples
33
+ # number_with_delimiter(12345678) # => 12,345,678
34
+ # number_with_delimiter(12345678.05) # => 12,345,678.05
35
+ # number_with_delimiter(12345678, :delimiter => ".") # => 12.345.678
36
+ # number_with_delimiter(12345678, :separator => ",") # => 12,345,678
37
+ # number_with_delimiter(98765432.98, :delimiter => " ", :separator => ",")
38
+ # # => 98 765 432,98
39
+ #
40
+ # You can still use <tt>number_with_delimiter</tt> with the old API that accepts the
41
+ # +delimiter+ as its optional second and the +separator+ as its
42
+ # optional third parameter:
43
+ # number_with_delimiter(12345678, " ") # => 12 345.678
44
+ # number_with_delimiter(12345678.05, ".", ",") # => 12.345.678,05
45
+ def number_with_delimiter(number, *args)
46
+ options = args.extract_options!
47
+ options.symbolize_keys!
48
+
49
+ unless args.empty?
50
+ ActiveSupport::Deprecation.warn('number_with_delimiter takes an option hash ' +
51
+ 'instead of separate delimiter and precision arguments.', caller)
52
+ delimiter = args[0] || '.'
53
+ separator = args[1] || ','
54
+ end
55
+
56
+ delimiter ||= (options[:delimiter] || '.')
57
+ separator ||= (options[:separator] || ',')
58
+
59
+ begin
60
+ parts = number.to_s.split('.')
61
+ parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{delimiter}")
62
+ parts.join(separator)
63
+ #rescue
64
+ # number
65
+ end
66
+ end
67
+
68
+ # Formats a +number+ with the specified level of <tt>:precision</tt> (e.g., 112.32 has a precision of 2).
69
+ # You can customize the format in the +options+ hash.
70
+ #
71
+ # ==== Options
72
+ # * <tt>:precision</tt> - Sets the level of precision (defaults to 3).
73
+ # * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
74
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
75
+ #
76
+ # ==== Examples
77
+ # number_with_precision(111.2345) # => 111.235
78
+ # number_with_precision(111.2345, :precision => 2) # => 111.23
79
+ # number_with_precision(13, :precision => 5) # => 13.00000
80
+ # number_with_precision(389.32314, :precision => 0) # => 389
81
+ # number_with_precision(1111.2345, :precision => 2, :separator => ',', :delimiter => '.')
82
+ # # => 1.111,23
83
+ #
84
+ # You can still use <tt>number_with_precision</tt> with the old API that accepts the
85
+ # +precision+ as its optional second parameter:
86
+ # number_with_precision(number_with_precision(111.2345, 2) # => 111.23
87
+ def number_with_precision(number, *args)
88
+ options = args.extract_options!
89
+ options.symbolize_keys!
90
+
91
+ precision ||= (options[:precision] || 3)
92
+ separator ||= (options[:separator] || '.')
93
+ delimiter ||= (options[:delimiter] || '')
94
+
95
+ begin
96
+ rounded_number = (Float(number) * (10 ** precision)).round.to_f / 10 ** precision
97
+ number_with_delimiter("%01.#{precision}f" % rounded_number,
98
+ :separator => separator,
99
+ :delimiter => delimiter)
100
+ #rescue
101
+ # number
102
+ end
103
+ end
104
+
105
+ # Formats the bytes in +size+ into a more understandable representation
106
+ # (e.g., giving it 1500 yields 1.5 KB). This method is useful for
107
+ # reporting file sizes to users. This method returns nil if
108
+ # +size+ cannot be converted into a number. You can customize the
109
+ # format in the +options+ hash.
110
+ #
111
+ # ==== Options
112
+ # * <tt>:base</tt> - Pass in 2 (or 1024) to use binary units (KiB, MiB),
113
+ # pass in 10 (or 1000) to use SI (decimal) units (KB, MB)
114
+ # (defaults to base 10).
115
+ # * <tt>:precision</tt> - Sets the level of precision (defaults to 1).
116
+ # * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
117
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
118
+ #
119
+ # ==== Examples
120
+ # number_to_human_size(123) # => 123 Bytes
121
+ # number_to_human_size(1234) # => 1.2 KB
122
+ # number_to_human_size(12345) # => 12.3 KB
123
+ # number_to_human_size(1234567) # => 1.2 MB
124
+ # number_to_human_size(1234567890) # => 1.2 GB
125
+ # number_to_human_size(1234567890123) # => 1.2 TB
126
+ # number_to_human_size(1234567, :precision => 2) # => 1.23 MB
127
+ # number_to_human_size(1234567, :precision => 2, :base => 2) # => 1.18 MiB
128
+ # number_to_human_size(483989, :precision => 0) # => 484 KB
129
+ # number_to_human_size(483989, :precision => 0, :base => 2) # => 473 KiB
130
+ # number_to_human_size(1234567, :precision => 2, :separator => ',') # => 1,23 MB
131
+ #
132
+ # ==== Differences from ActiveSupport version
133
+ # The ActiveSupport version defaults to binary (base 2) units, while this one
134
+ # defaults to SI (base 10) units.
135
+ #
136
+ # The ActiveSupport incorrectly uses KB to refer to binary units, when the correct
137
+ # abbreviation would be KiB (see http://en.wikipedia.org/wiki/Binary_prefix).
138
+ #
139
+ # This version has a :base option to let you change the base; the ActiveSupport
140
+ # version does not.
141
+ #
142
+ def number_to_human_size(number, *args)
143
+ return nil if number.nil?
144
+
145
+ options = args.extract_options!
146
+ options.symbolize_keys!
147
+
148
+ precision ||= (options[:precision] || 1)
149
+ separator ||= (options[:separator] || '.')
150
+ delimiter ||= (options[:delimiter] || ',')
151
+ base ||= (options[:base] || 10)
152
+
153
+ # http://en.wikipedia.org/wiki/Binary_prefix
154
+ if base == 10 || base == 1000
155
+ storage_units = %w( Bytes KB MB GB TB ).freeze
156
+ base = 1000
157
+ elsif base == 2 || base == 1024
158
+ storage_units = %w( Bytes KiB MiB GiB TiB ).freeze
159
+ base = 1024
160
+ else
161
+ raise ArgumentError, "base must be 1000 or 1024"
162
+ end
163
+ storage_units_format = '%n %u'
164
+
165
+ if number.to_i < base
166
+ unit = number.to_i == 1 ? 'byte' : 'bytes'
167
+ storage_units_format.gsub(/%n/, number.to_i.to_s).gsub(/%u/, unit)
168
+ else
169
+ max_exp = storage_units.size - 1
170
+ number = Float(number)
171
+ exponent = (Math.log(number) / Math.log(base)).to_i # Convert to base 1024
172
+ exponent = max_exp if exponent > max_exp # we need this to avoid overflow for the highest unit
173
+ number /= base ** exponent
174
+
175
+ unit = storage_units[exponent]
176
+
177
+ begin
178
+ escaped_separator = Regexp.escape(separator)
179
+ formatted_number = number_with_precision(number,
180
+ :precision => precision,
181
+ :separator => separator,
182
+ :delimiter => delimiter
183
+ ).sub(/(\d)(#{escaped_separator}[1-9]*)?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '')
184
+ storage_units_format.gsub(/%n/, formatted_number).gsub(/%u/, unit)
185
+ #rescue
186
+ # number
187
+ end
188
+ end
189
+ end
190
+ end
191
+
192
+
193
+ # _____ _
194
+ # |_ _|__ ___| |_
195
+ # | |/ _ \/ __| __|
196
+ # | | __/\__ \ |_
197
+ # |_|\___||___/\__|
198
+ #
199
+ =begin test
200
+ require 'spec/autorun'
201
+
202
+ describe 'number_to_human_size' do
203
+ it 'uses decimal unit (KB) when using base 1000' do
204
+ number_to_human_size(524288, :base => 1000).should match(/ KB$/)
205
+ end
206
+
207
+ it 'uses the correct conversion when using base 1000' do
208
+ number_to_human_size(524288, :base => 1000).should match(/^524\.3 /)
209
+ end
210
+
211
+ it 'uses binary unit (KiB) when using base 1024' do
212
+ number_to_human_size(524288, :base => 1024).should match(/ KiB$/)
213
+ end
214
+
215
+ it 'uses the correct conversion when using base 1024' do
216
+ number_to_human_size(524288, :base => 1024).should match(/^512 /)
217
+ end
218
+ end
219
+
220
+ describe 'number_to_human_size examples' do
221
+ it '1234' do
222
+ number_to_human_size(123).should == '123 bytes'
223
+ end
224
+
225
+ it '12345' do
226
+ number_to_human_size(12345).should == '12.3 KB'
227
+ end
228
+
229
+ it '1234567' do
230
+ number_to_human_size(1234567).should == '1.2 MB'
231
+ number_to_human_size(1234567, :base => 2).should == '1.2 MiB'
232
+ end
233
+
234
+ it '1234567890' do
235
+ number_to_human_size(1234567890).should == '1.2 GB'
236
+ end
237
+
238
+ it '1234567890123' do
239
+ number_to_human_size(1234567890123).should == '1.2 TB'
240
+ end
241
+
242
+ it '1234567' do
243
+ number_to_human_size(1234567, :precision => 2).should == '1.23 MB'
244
+ number_to_human_size(1234567, :precision => 2, :base => 2).should == '1.18 MiB'
245
+ end
246
+
247
+ it '483989' do
248
+ number_to_human_size(483989, :precision => 0).should == '484 KB'
249
+ number_to_human_size(483989, :precision => 0, :base => 2).should == '473 KiB'
250
+ end
251
+
252
+ it '1234567' do
253
+ number_to_human_size(1234567, :precision => 2, :separator => ',').should == '1,23 MB'
254
+ end
255
+ end
256
+
257
+
258
+ =end
259
+
@@ -25,8 +25,8 @@ $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
25
25
  require 'test/unit'
26
26
  require 'rubygems'
27
27
  require 'quality_extensions/kernel/capture_output'
28
- #require 'facets/kernel/require_local'
29
- #require_local './capture_output'
28
+ #require 'facets/kernel/require_relative'
29
+ #require_relative './capture_output'
30
30
 
31
31
  class TheTest < Test::Unit::TestCase
32
32