gorillib 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/LICENSE.textile +81 -0
- data/README.textile +153 -0
- data/Rakefile +26 -0
- data/VERSION +1 -0
- data/fiddle/hubahuba.rb +62 -0
- data/gorillib.gemspec +142 -0
- data/lib/gorillib/array/compact_blank.rb +17 -0
- data/lib/gorillib/array/extract_options.rb +29 -0
- data/lib/gorillib/base.rb +7 -0
- data/lib/gorillib/datetime/flat.rb +29 -0
- data/lib/gorillib/datetime/parse.rb +21 -0
- data/lib/gorillib/enumerable/sum.rb +38 -0
- data/lib/gorillib/hash/compact.rb +31 -0
- data/lib/gorillib/hash/deep_merge.rb +16 -0
- data/lib/gorillib/hash/keys.rb +42 -0
- data/lib/gorillib/hash/reverse_merge.rb +26 -0
- data/lib/gorillib/hash/slice.rb +53 -0
- data/lib/gorillib/hash/zip.rb +10 -0
- data/lib/gorillib/logger/log.rb +14 -0
- data/lib/gorillib/metaprogramming/aliasing.rb +43 -0
- data/lib/gorillib/metaprogramming/cattr_accessor.rb +79 -0
- data/lib/gorillib/metaprogramming/class_attribute.rb +90 -0
- data/lib/gorillib/metaprogramming/delegation.rb +146 -0
- data/lib/gorillib/metaprogramming/mattr_accessor.rb +61 -0
- data/lib/gorillib/metaprogramming/remove_method.rb +11 -0
- data/lib/gorillib/metaprogramming/singleton_class.rb +8 -0
- data/lib/gorillib/object/blank.rb +89 -0
- data/lib/gorillib/some.rb +12 -0
- data/lib/gorillib/string/constantize.rb +21 -0
- data/lib/gorillib/string/human.rb +52 -0
- data/lib/gorillib/string/inflections.rb +78 -0
- data/lib/gorillib/string/truncate.rb +33 -0
- data/lib/gorillib.rb +1 -0
- data/spec/blank_spec.rb +86 -0
- data/spec/gorillib_spec.rb +7 -0
- data/spec/rcov.opts +6 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/spec_tasks.rake +15 -0
- data/test/abstract_unit.rb +25 -0
- data/test/array/compact_blank_test.rb +33 -0
- data/test/array/extract_options_test.rb +39 -0
- data/test/datetime/flat_test.rb +0 -0
- data/test/datetime/parse_test.rb +0 -0
- data/test/enumerable/sum_test.rb +50 -0
- data/test/hash/compact_test.rb +38 -0
- data/test/hash/deep_merge_test.rb +30 -0
- data/test/hash/keys_test.rb +110 -0
- data/test/hash/reverse_merge_test.rb +20 -0
- data/test/hash/slice_test.rb +47 -0
- data/test/hash/zip_test.rb +0 -0
- data/test/logger/log_test.rb +0 -0
- data/test/metaprogramming/aliasing_test.rb +188 -0
- data/test/metaprogramming/cattr_accessor_test.rb +38 -0
- data/test/metaprogramming/class_attribute_test.rb +73 -0
- data/test/metaprogramming/delegation_test.rb +166 -0
- data/test/metaprogramming/mattr_accessor_test.rb +40 -0
- data/test/metaprogramming/singleton_class_test.rb +9 -0
- data/test/object/blank_test.rb +22 -0
- data/test/string/constantize_test.rb +30 -0
- data/test/string/human_test.rb +65 -0
- data/test/string/inflections_test.rb +57 -0
- data/test/string/inflector_test_cases.rb +50 -0
- data/test/string/truncate_test.rb +37 -0
- metadata +199 -0
@@ -0,0 +1,89 @@
|
|
1
|
+
class Object
|
2
|
+
##
|
3
|
+
# Returns true if the object is nil or empty (if applicable)
|
4
|
+
#
|
5
|
+
# [].blank? #=> true
|
6
|
+
# [1].blank? #=> false
|
7
|
+
# [nil].blank? #=> false
|
8
|
+
#
|
9
|
+
# @return [TrueClass, FalseClass]
|
10
|
+
#
|
11
|
+
# @api public
|
12
|
+
def blank?
|
13
|
+
nil? || (respond_to?(:empty?) && empty?)
|
14
|
+
end
|
15
|
+
end # class Object
|
16
|
+
|
17
|
+
class Numeric
|
18
|
+
##
|
19
|
+
# Numerics are never blank
|
20
|
+
#
|
21
|
+
# 0.blank? #=> false
|
22
|
+
# 1.blank? #=> false
|
23
|
+
# 6.54321.blank? #=> false
|
24
|
+
#
|
25
|
+
# @return [FalseClass]
|
26
|
+
#
|
27
|
+
# @api public
|
28
|
+
def blank?
|
29
|
+
false
|
30
|
+
end
|
31
|
+
end # class Numeric
|
32
|
+
|
33
|
+
class NilClass
|
34
|
+
##
|
35
|
+
# Nil is always blank
|
36
|
+
#
|
37
|
+
# nil.blank? #=> true
|
38
|
+
#
|
39
|
+
# @return [TrueClass]
|
40
|
+
#
|
41
|
+
# @api public
|
42
|
+
def blank?
|
43
|
+
true
|
44
|
+
end
|
45
|
+
end # class NilClass
|
46
|
+
|
47
|
+
class TrueClass
|
48
|
+
##
|
49
|
+
# True is never blank.
|
50
|
+
#
|
51
|
+
# true.blank? #=> false
|
52
|
+
#
|
53
|
+
# @return [FalseClass]
|
54
|
+
#
|
55
|
+
# @api public
|
56
|
+
def blank?
|
57
|
+
false
|
58
|
+
end
|
59
|
+
end # class TrueClass
|
60
|
+
|
61
|
+
class FalseClass
|
62
|
+
##
|
63
|
+
# False is always blank.
|
64
|
+
#
|
65
|
+
# false.blank? #=> true
|
66
|
+
#
|
67
|
+
# @return [TrueClass]
|
68
|
+
#
|
69
|
+
# @api public
|
70
|
+
def blank?
|
71
|
+
true
|
72
|
+
end
|
73
|
+
end # class FalseClass
|
74
|
+
|
75
|
+
class String
|
76
|
+
##
|
77
|
+
# Strips out whitespace then tests if the string is empty.
|
78
|
+
#
|
79
|
+
# "".blank? #=> true
|
80
|
+
# " ".blank? #=> true
|
81
|
+
# " hey ho ".blank? #=> false
|
82
|
+
#
|
83
|
+
# @return [TrueClass, FalseClass]
|
84
|
+
#
|
85
|
+
# @api public
|
86
|
+
def blank?
|
87
|
+
strip.empty?
|
88
|
+
end
|
89
|
+
end # class String
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'gorillib/base'
|
2
|
+
require 'set'
|
3
|
+
require 'time'
|
4
|
+
require 'date'
|
5
|
+
require 'gorillib/array/compact_flat'
|
6
|
+
require 'gorillib/hash/compact'
|
7
|
+
require 'gorillib/enumerable/sum'
|
8
|
+
require 'gorillib/datetime/flat'
|
9
|
+
require 'gorillib/datetime/parse'
|
10
|
+
require 'gorillib/hash/zip'
|
11
|
+
require 'gorillib/hash/slice'
|
12
|
+
require 'gorillib/hash/keys'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class String
|
2
|
+
|
3
|
+
# Constantize tries to find a declared constant with the name specified
|
4
|
+
# in the string. It raises a NameError when the name is not in CamelCase
|
5
|
+
# or is not initialized.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# "Module".constantize #=> Module
|
9
|
+
# "Class".constantize #=> Class
|
10
|
+
#
|
11
|
+
# This is the extlib version of String#constantize, which has different
|
12
|
+
# behavior wrt using lexical context: see active_support/inflector/methods.rb
|
13
|
+
#
|
14
|
+
def constantize
|
15
|
+
unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ self
|
16
|
+
raise NameError, "#{self.inspect} is not a valid constant name!"
|
17
|
+
end
|
18
|
+
|
19
|
+
Object.module_eval("::#{$1}", __FILE__, __LINE__)
|
20
|
+
end unless method_defined?(:constantize)
|
21
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'gorillib/string/inflections'
|
2
|
+
require 'gorillib/array/extract_options'
|
3
|
+
|
4
|
+
class String
|
5
|
+
|
6
|
+
# Capitalizes the first word and turns underscores into spaces and strips a
|
7
|
+
# trailing "_id", if any. Like +titleize+, this is meant for creating pretty output.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# "employee_salary" #=> "Employee salary"
|
11
|
+
# "author_id" #=> "Author"
|
12
|
+
def humanize
|
13
|
+
self.gsub(/_id$/, '').tr('_', ' ').capitalize
|
14
|
+
end unless method_defined?(:humanize)
|
15
|
+
|
16
|
+
# Capitalizes all the words and replaces some characters in the string to create
|
17
|
+
# a nicer looking title. +titleize+ is meant for creating pretty output. It is not
|
18
|
+
# used in the Rails internals.
|
19
|
+
#
|
20
|
+
# Examples:
|
21
|
+
# "man from the boondocks".titleize # => "Man From The Boondocks"
|
22
|
+
# "x-men: the last stand".titleize # => "X Men: The Last Stand"
|
23
|
+
def titleize
|
24
|
+
self.underscore.humanize.gsub(/\b('?[a-z])/){ $1.capitalize }
|
25
|
+
end unless method_defined?(:titleize)
|
26
|
+
end
|
27
|
+
|
28
|
+
class Array
|
29
|
+
# Converts the array to a comma-separated sentence where the last element is joined by the connector word. Options:
|
30
|
+
# * <tt>:words_connector</tt> - The sign or word used to join the elements in arrays with two or more elements (default: ", ")
|
31
|
+
# * <tt>:two_words_connector</tt> - The sign or word used to join the elements in arrays with two elements (default: " and ")
|
32
|
+
# * <tt>:last_word_connector</tt> - The sign or word used to join the last element in arrays with three or more elements (default: ", and ")
|
33
|
+
def to_sentence(options = {})
|
34
|
+
default_words_connector = ", "
|
35
|
+
default_two_words_connector = " and "
|
36
|
+
default_last_word_connector = ", and "
|
37
|
+
|
38
|
+
options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
|
39
|
+
options.reverse_merge! :words_connector => default_words_connector, :two_words_connector => default_two_words_connector, :last_word_connector => default_last_word_connector
|
40
|
+
|
41
|
+
case length
|
42
|
+
when 0
|
43
|
+
""
|
44
|
+
when 1
|
45
|
+
self[0].to_s.dup
|
46
|
+
when 2
|
47
|
+
"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
|
48
|
+
else
|
49
|
+
"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
|
50
|
+
end
|
51
|
+
end unless method_defined?(:to_sentence)
|
52
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# String inflections define new methods on the String class to transform names for different purposes.
|
2
|
+
#
|
3
|
+
# "ScaleScore".underscore # => "scale_score"
|
4
|
+
#
|
5
|
+
# This doesn't define the full set of inflections -- only
|
6
|
+
#
|
7
|
+
# * camelize
|
8
|
+
# * snakeize
|
9
|
+
# * underscore
|
10
|
+
# * demodulize
|
11
|
+
#
|
12
|
+
class String
|
13
|
+
|
14
|
+
# By default, +camelize+ converts strings to UpperCamelCase. If the argument to +camelize+
|
15
|
+
# is set to <tt>:lower</tt> then +camelize+ produces lowerCamelCase.
|
16
|
+
#
|
17
|
+
# +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces.
|
18
|
+
#
|
19
|
+
# @example:
|
20
|
+
# "active_record".camelize # => "ActiveRecord"
|
21
|
+
# "active_record".camelize(:lower) # => "activeRecord"
|
22
|
+
# "active_record/errors".camelize # => "ActiveRecord::Errors"
|
23
|
+
# "active_record/errors".camelize(:lower) # => "activeRecord::Errors"
|
24
|
+
#
|
25
|
+
# As a rule of thumb you can think of +camelize+ as the inverse of +underscore+,
|
26
|
+
# though there are cases where that does not hold:
|
27
|
+
#
|
28
|
+
# "SSLError".underscore.camelize # => "SslError"
|
29
|
+
#
|
30
|
+
def camelize(first_letter = :upper)
|
31
|
+
camelized = self.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
32
|
+
(first_letter == :lower) ? (self[0..0].downcase + camelized[1..-1]) : camelized
|
33
|
+
end unless method_defined?(:camelize)
|
34
|
+
|
35
|
+
# Converts strings to snakeCase, also known as lowerCamelCase.
|
36
|
+
#
|
37
|
+
# +snakeize+ will also convert '/' to '::' which is useful for converting paths to namespaces.
|
38
|
+
#
|
39
|
+
# @example:
|
40
|
+
# "active_record".snakeize # => "activeRecord"
|
41
|
+
# "active_record/errors".snakeize # => "activeRecord::Errors"
|
42
|
+
#
|
43
|
+
def snakeize
|
44
|
+
camelize :lower
|
45
|
+
end unless method_defined?(:snakeize)
|
46
|
+
|
47
|
+
# Makes an underscored, lowercase form from the expression in the string.
|
48
|
+
#
|
49
|
+
# +underscore+ will also change '::' to '/' to convert namespaces to paths.
|
50
|
+
#
|
51
|
+
# Examples:
|
52
|
+
# "ActiveRecord".underscore # => "active_record"
|
53
|
+
# "ActiveRecord::Errors".underscore # => active_record/errors
|
54
|
+
#
|
55
|
+
# As a rule of thumb you can think of +underscore+ as the inverse of +camelize+,
|
56
|
+
# though there are cases where that does not hold:
|
57
|
+
#
|
58
|
+
# "SSLError".underscore.camelize # => "SslError"
|
59
|
+
def underscore
|
60
|
+
word = self.dup
|
61
|
+
word.gsub!(/::/, '/')
|
62
|
+
word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
63
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
64
|
+
word.tr!("-", "_")
|
65
|
+
word.downcase!
|
66
|
+
word
|
67
|
+
end unless method_defined?(:underscore)
|
68
|
+
|
69
|
+
# Removes the module part from the expression in the string
|
70
|
+
#
|
71
|
+
# @example
|
72
|
+
# "ActiveRecord::CoreExtensions::String::Inflections".demodulize #=> "Inflections"
|
73
|
+
# "Inflections".demodulize #=> "Inflections"
|
74
|
+
def demodulize
|
75
|
+
self.gsub(/^.*::/, '')
|
76
|
+
end unless method_defined?(:demodulize)
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class String
|
2
|
+
# Truncates a given +text+ after a given <tt>length</tt> if +text+ is longer than <tt>length</tt>:
|
3
|
+
#
|
4
|
+
# "Once upon a time in a world far far away".truncate(27)
|
5
|
+
# # => "Once upon a time in a wo..."
|
6
|
+
#
|
7
|
+
# The last characters will be replaced with the <tt>:omission</tt> string (defaults to "...")
|
8
|
+
# for a total length not exceeding <tt>:length</tt>:
|
9
|
+
#
|
10
|
+
# "Once upon a time in a world far far away".truncate(27, :separator => ' ')
|
11
|
+
# # => "Once upon a time in a..."
|
12
|
+
#
|
13
|
+
# Pass a <tt>:separator</tt> to truncate +text+ at a natural break:
|
14
|
+
#
|
15
|
+
# "And they found that many people were sleeping better.".truncate(25, :omission => "... (continued)")
|
16
|
+
# # => "And they f... (continued)"
|
17
|
+
def truncate(length, options = {})
|
18
|
+
text = self.dup
|
19
|
+
chars = text.respond_to?(:mb_chars) ? text.mb_chars : text.chars
|
20
|
+
omission = options[:omission] || "..."
|
21
|
+
omission_len = omission.respond_to?(:mb_chars) ? omission.mb_chars.length : omission.length
|
22
|
+
length_with_room_for_omission = length - omission_len
|
23
|
+
|
24
|
+
if (separator = options[:separator])
|
25
|
+
separator_chars = separator.respond_to?(:mb_chars) ? separator.to_s.mb_chars : separator.to_s.chars
|
26
|
+
stop = chars.rindex(separator_chars, length_with_room_for_omission) || length_with_room_for_omission
|
27
|
+
else
|
28
|
+
stop = length_with_room_for_omission
|
29
|
+
end
|
30
|
+
|
31
|
+
(chars.length > length ? chars[0...stop] + omission : text).to_s
|
32
|
+
end unless method_defined?(:truncate)
|
33
|
+
end
|
data/lib/gorillib.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'gorillib/base'
|
data/spec/blank_spec.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'extlib/blank'
|
3
|
+
|
4
|
+
describe Object do
|
5
|
+
it 'should provide blank?' do
|
6
|
+
Object.new.should respond_to(:blank?)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should be blank if it is nil' do
|
10
|
+
object = Object.new
|
11
|
+
class << object
|
12
|
+
def nil?; true end
|
13
|
+
end
|
14
|
+
object.should be_blank
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should be blank if it is empty' do
|
18
|
+
{}.should be_blank
|
19
|
+
[].should be_blank
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should not be blank if not nil or empty' do
|
23
|
+
Object.new.should_not be_blank
|
24
|
+
[nil].should_not be_blank
|
25
|
+
{ nil => 0 }.should_not be_blank
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe Numeric do
|
30
|
+
it 'should provide blank?' do
|
31
|
+
1.should respond_to(:blank?)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should never be blank' do
|
35
|
+
1.should_not be_blank
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe NilClass do
|
40
|
+
it 'should provide blank?' do
|
41
|
+
nil.should respond_to(:blank?)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should always be blank' do
|
45
|
+
nil.should be_blank
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe TrueClass do
|
50
|
+
it 'should provide blank?' do
|
51
|
+
true.should respond_to(:blank?)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should never be blank' do
|
55
|
+
true.should_not be_blank
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe FalseClass do
|
60
|
+
it 'should provide blank?' do
|
61
|
+
false.should respond_to(:blank?)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should always be blank' do
|
65
|
+
false.should be_blank
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe String do
|
70
|
+
it 'should provide blank?' do
|
71
|
+
'string'.should respond_to(:blank?)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should be blank if empty' do
|
75
|
+
''.should be_blank
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should be blank if it only contains whitespace' do
|
79
|
+
' '.should be_blank
|
80
|
+
" \r \n \t ".should be_blank
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should not be blank if it contains non-whitespace' do
|
84
|
+
' a '.should_not be_blank
|
85
|
+
end
|
86
|
+
end
|
data/spec/rcov.opts
ADDED
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'gorillib'
|
5
|
+
|
6
|
+
# Requires supporting files with custom matchers and macros, etc,
|
7
|
+
# in ./support/ and its subdirectories.
|
8
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rspec/core'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
7
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
8
|
+
end
|
9
|
+
|
10
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
11
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
12
|
+
spec.rcov = true
|
13
|
+
end
|
14
|
+
|
15
|
+
task :default => :spec
|
@@ -0,0 +1,25 @@
|
|
1
|
+
ORIG_ARGV = ARGV.dup
|
2
|
+
|
3
|
+
curr = File.expand_path(File.dirname(__FILE__))
|
4
|
+
$:.unshift(curr) unless $:.include?('curr') || $:.include?(curr)
|
5
|
+
lib = File.expand_path("#{File.dirname(__FILE__)}/../lib")
|
6
|
+
$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib)
|
7
|
+
|
8
|
+
require 'test/unit'
|
9
|
+
|
10
|
+
def with_kcode(code)
|
11
|
+
if RUBY_VERSION < '1.9'
|
12
|
+
begin
|
13
|
+
old_kcode, $KCODE = $KCODE, code
|
14
|
+
yield
|
15
|
+
ensure
|
16
|
+
$KCODE = old_kcode
|
17
|
+
end
|
18
|
+
else
|
19
|
+
yield
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
if RUBY_VERSION < '1.9'
|
24
|
+
$KCODE = 'UTF8'
|
25
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/../abstract_unit'
|
2
|
+
require 'gorillib/array/compact_blank'
|
3
|
+
|
4
|
+
class ArrayCompactBlankTests < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_compact_blank_with_empty
|
7
|
+
[ [nil], [nil, false, {}, ""] ].each do |arr|
|
8
|
+
assert_equal([], arr.compact_blank)
|
9
|
+
assert_not_equal(0, arr.length)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_compact_blank_bang_with_empty
|
14
|
+
assert_equal([], [].compact_blank!)
|
15
|
+
#
|
16
|
+
[ [nil], [nil, false, {}, ""] ].each do |arr|
|
17
|
+
assert_equal([], arr.compact_blank!)
|
18
|
+
assert_equal(0, arr.length)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_compact_blank_with_full
|
23
|
+
[ [nil, 1, nil, 2], [nil, 1, false, 2, {}, ""] ].each do |arr|
|
24
|
+
assert_equal([1, 2], arr.compact_blank)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_compact_blank_bang_with_full
|
29
|
+
[ [nil, 1, nil, 2], [nil, 1, false, 2, {}, ""] ].each do |arr|
|
30
|
+
assert_equal([1, 2], arr.compact_blank!)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/../abstract_unit'
|
2
|
+
require 'gorillib/array/extract_options'
|
3
|
+
|
4
|
+
class ArrayExtractOptionsTests < Test::Unit::TestCase
|
5
|
+
class HashSubclass < Hash
|
6
|
+
end
|
7
|
+
|
8
|
+
class ExtractableHashSubclass < Hash
|
9
|
+
def extractable_options?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_extract_options
|
15
|
+
assert_equal({}, [].extract_options!)
|
16
|
+
assert_equal({}, [1].extract_options!)
|
17
|
+
assert_equal({:a=>:b}, [{:a=>:b}].extract_options!)
|
18
|
+
assert_equal({:a=>:b}, [1, {:a=>:b}].extract_options!)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_extract_options_doesnt_extract_hash_subclasses
|
22
|
+
hash = HashSubclass.new
|
23
|
+
hash[:foo] = 1
|
24
|
+
array = [hash]
|
25
|
+
options = array.extract_options!
|
26
|
+
assert_equal({}, options)
|
27
|
+
assert_equal [hash], array
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_extract_options_extracts_extractable_subclass
|
31
|
+
hash = ExtractableHashSubclass.new
|
32
|
+
hash[:foo] = 1
|
33
|
+
array = [hash]
|
34
|
+
options = array.extract_options!
|
35
|
+
assert_equal({:foo => 1}, options)
|
36
|
+
assert_equal [], array
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
File without changes
|
File without changes
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/../abstract_unit'
|
2
|
+
require 'gorillib/enumerable/sum'
|
3
|
+
|
4
|
+
Payment = Struct.new(:price)
|
5
|
+
class SummablePayment < Payment
|
6
|
+
def +(p) self.class.new(price + p.price) end
|
7
|
+
end
|
8
|
+
|
9
|
+
class EnumerableTests < Test::Unit::TestCase
|
10
|
+
def test_sums
|
11
|
+
assert_equal 30, [5, 15, 10].sum
|
12
|
+
assert_equal 30, [5, 15, 10].sum { |i| i }
|
13
|
+
|
14
|
+
assert_equal 'abc', %w(a b c).sum
|
15
|
+
assert_equal 'abc', %w(a b c).sum { |i| i }
|
16
|
+
|
17
|
+
payments = [ Payment.new(5), Payment.new(15), Payment.new(10) ]
|
18
|
+
assert_equal 30, payments.sum(&:price)
|
19
|
+
assert_equal 60, payments.sum { |p| p.price * 2 }
|
20
|
+
|
21
|
+
payments = [ SummablePayment.new(5), SummablePayment.new(15) ]
|
22
|
+
assert_equal SummablePayment.new(20), payments.sum
|
23
|
+
assert_equal SummablePayment.new(20), payments.sum { |p| p }
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_nil_sums
|
27
|
+
expected_raise = TypeError
|
28
|
+
|
29
|
+
assert_raise(expected_raise) { [5, 15, nil].sum }
|
30
|
+
|
31
|
+
payments = [ Payment.new(5), Payment.new(15), Payment.new(10), Payment.new(nil) ]
|
32
|
+
assert_raise(expected_raise) { payments.sum(&:price) }
|
33
|
+
|
34
|
+
assert_equal 60, payments.sum { |p| p.price.to_i * 2 }
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_empty_sums
|
38
|
+
assert_equal 0, [].sum
|
39
|
+
assert_equal 0, [].sum { |i| i }
|
40
|
+
assert_equal Payment.new(0), [].sum(Payment.new(0))
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_enumerable_sums
|
44
|
+
assert_equal 20, (1..4).sum { |i| i * 2 }
|
45
|
+
assert_equal 10, (1..4).sum
|
46
|
+
assert_equal 10, (1..4.5).sum
|
47
|
+
assert_equal 6, (1...4).sum
|
48
|
+
assert_equal 'abc', ('a'..'c').sum
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/../abstract_unit'
|
2
|
+
require 'gorillib/hash/compact'
|
3
|
+
|
4
|
+
class HashCompactTests < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_compact_blank_with_empty
|
7
|
+
[ { 1 => nil}, { 1 => nil, 2 => false, 3 => {}, 4 => ""} ].each do |hsh|
|
8
|
+
assert_equal({}, hsh.compact_blank)
|
9
|
+
assert_not_equal(0, hsh.length)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_compact_blank_with_empty
|
14
|
+
[ { 1 => nil}, { 1 => nil, 2 => false, 3 => {}, 4 => ""} ].each do |hsh|
|
15
|
+
assert_equal({}, hsh.compact_blank!)
|
16
|
+
assert_equal(0, hsh.length)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_compact_blank_with_full
|
21
|
+
assert_equal(
|
22
|
+
{ nil => 2 },
|
23
|
+
{ 1 => nil, nil => 2 }.compact_blank )
|
24
|
+
assert_equal(
|
25
|
+
{ 2 => :val_2, 4 => :val_4 },
|
26
|
+
{ 1 => nil, 2 => :val_2, 3 => {}, 4 => :val_4}.compact_blank )
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_compact_blank_bang_with_full
|
30
|
+
assert_equal(
|
31
|
+
{ nil => 2 },
|
32
|
+
{ 1 => nil, nil => 2 }.compact_blank! )
|
33
|
+
assert_equal(
|
34
|
+
{ 2 => :val_2, 4 => :val_4 },
|
35
|
+
{ 1 => nil, 2 => :val_2, 3 => {}, 4 => :val_4}.compact_blank! )
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/../abstract_unit'
|
2
|
+
require 'gorillib/hash/deep_merge'
|
3
|
+
|
4
|
+
class HashDeepMergeTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_deep_merge
|
7
|
+
hash_1 = { :a => "a", :b => "b", :c => { :c1 => "c1", :c2 => "c2", :c3 => { :d1 => "d1" } } }
|
8
|
+
hash_2 = { :a => 1, :c => { :c1 => 2, :c3 => { :d2 => "d2" } } }
|
9
|
+
expected = { :a => 1, :b => "b", :c => { :c1 => 2, :c2 => "c2", :c3 => { :d1 => "d1", :d2 => "d2" } } }
|
10
|
+
assert_equal expected, hash_1.deep_merge(hash_2)
|
11
|
+
|
12
|
+
hash_1.deep_merge!(hash_2)
|
13
|
+
assert_equal expected, hash_1
|
14
|
+
end
|
15
|
+
|
16
|
+
# def test_deep_dup
|
17
|
+
# hash = { :a => { :b => 'b' } }
|
18
|
+
# dup = hash.deep_dup
|
19
|
+
# dup[:a][:c] = 'c'
|
20
|
+
# assert_equal nil, hash[:a][:c]
|
21
|
+
# assert_equal 'c', dup[:a][:c]
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# def test_deep_dup_initialize
|
25
|
+
# zero_hash = Hash.new 0
|
26
|
+
# hash = { :a => zero_hash }
|
27
|
+
# dup = hash.deep_dup
|
28
|
+
# assert_equal 0, dup[:a][44]
|
29
|
+
# end
|
30
|
+
end
|