quality_extensions 1.1.6 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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