gorillib 0.0.2
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.
- 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
|