gorillib 0.0.7 → 0.0.8

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 (84) hide show
  1. data/.gitignore +49 -0
  2. data/.rspec +2 -0
  3. data/CHANGELOG.textile +49 -0
  4. data/Gemfile +15 -0
  5. data/Gemfile.lock +36 -0
  6. data/README.textile +6 -1
  7. data/Rakefile +42 -9
  8. data/VERSION +1 -1
  9. data/gorillib.gemspec +110 -73
  10. data/lib/gorillib/array/deep_compact.rb +3 -12
  11. data/lib/gorillib/datetime/#flat.rb# +30 -0
  12. data/lib/gorillib/datetime/flat.rb +2 -10
  13. data/lib/gorillib/datetime/parse.rb +3 -1
  14. data/lib/gorillib/enumerable/sum.rb +37 -35
  15. data/lib/gorillib/hash/deep_compact.rb +3 -13
  16. data/lib/gorillib/logger/log.rb +1 -1
  17. data/lib/gorillib/numeric/clamp.rb +9 -0
  18. data/lib/gorillib/object/try.rb +10 -0
  19. data/lib/gorillib/object/try_dup.rb +44 -0
  20. data/lib/gorillib/string/human.rb +1 -3
  21. data/lib/gorillib/string/truncate.rb +2 -2
  22. data/spec/array/compact_blank_spec.rb +37 -0
  23. data/spec/array/extract_options_spec.rb +47 -0
  24. data/spec/datetime/flat_spec.rb +38 -0
  25. data/spec/datetime/parse_spec.rb +48 -0
  26. data/spec/enumerable/sum_spec.rb +56 -0
  27. data/spec/hash/compact_spec.rb +70 -0
  28. data/spec/hash/deep_compact_spec.rb +37 -0
  29. data/spec/hash/deep_merge_spec.rb +117 -0
  30. data/spec/hash/keys_spec.rb +111 -0
  31. data/spec/hash/reverse_merge_spec.rb +25 -0
  32. data/spec/hash/slice_spec.rb +43 -0
  33. data/spec/hash/zip_spec.rb +31 -0
  34. data/spec/logger/log_spec.rb +31 -0
  35. data/spec/metaprogramming/aliasing_spec.rb +177 -0
  36. data/spec/metaprogramming/cattr_accessor_spec.rb +41 -0
  37. data/spec/metaprogramming/class_attribute_spec.rb +75 -0
  38. data/spec/metaprogramming/delegation_spec.rb +166 -0
  39. data/spec/metaprogramming/mattr_accessor_spec.rb +44 -0
  40. data/spec/metaprogramming/singleton_class_spec.rb +9 -0
  41. data/spec/{numeric_spec.rb → numeric/clamp_spec.rb} +2 -2
  42. data/spec/object/blank_spec.rb +93 -0
  43. data/spec/object/try_dup_spec.rb +47 -0
  44. data/spec/object/try_spec.rb +20 -0
  45. data/spec/spec_helper.rb +13 -8
  46. data/spec/string/constantize_spec.rb +56 -0
  47. data/spec/string/human_spec.rb +66 -0
  48. data/spec/string/inflections_spec.rb +74 -0
  49. data/{test → spec}/string/inflector_test_cases.rb +0 -0
  50. data/spec/string/truncate_spec.rb +42 -0
  51. data/spec/support/kcode_test_helper.rb +16 -0
  52. metadata +209 -96
  53. data/.document +0 -5
  54. data/fiddle/hubahuba.rb +0 -62
  55. data/spec/blank_spec.rb +0 -86
  56. data/spec/deep_compact_spec.rb +0 -36
  57. data/spec/gorillib_spec.rb +0 -7
  58. data/spec/rcov.opts +0 -6
  59. data/spec/spec.opts +0 -4
  60. data/spec/spec_tasks.rake +0 -15
  61. data/test/abstract_unit.rb +0 -25
  62. data/test/array/compact_blank_test.rb +0 -33
  63. data/test/array/extract_options_test.rb +0 -39
  64. data/test/datetime/flat_test.rb +0 -0
  65. data/test/datetime/parse_test.rb +0 -0
  66. data/test/enumerable/sum_test.rb +0 -50
  67. data/test/hash/compact_test.rb +0 -38
  68. data/test/hash/deep_merge_test.rb +0 -30
  69. data/test/hash/keys_test.rb +0 -110
  70. data/test/hash/reverse_merge_test.rb +0 -20
  71. data/test/hash/slice_test.rb +0 -47
  72. data/test/hash/zip_test.rb +0 -0
  73. data/test/logger/log_test.rb +0 -0
  74. data/test/metaprogramming/aliasing_test.rb +0 -188
  75. data/test/metaprogramming/cattr_accessor_test.rb +0 -38
  76. data/test/metaprogramming/class_attribute_test.rb +0 -73
  77. data/test/metaprogramming/delegation_test.rb +0 -166
  78. data/test/metaprogramming/mattr_accessor_test.rb +0 -40
  79. data/test/metaprogramming/singleton_class_test.rb +0 -9
  80. data/test/object/blank_test.rb +0 -22
  81. data/test/string/constantize_test.rb +0 -30
  82. data/test/string/human_test.rb +0 -65
  83. data/test/string/inflections_test.rb +0 -57
  84. data/test/string/truncate_test.rb +0 -37
@@ -6,19 +6,9 @@ require 'gorillib/object/blank'
6
6
  class Hash
7
7
  def deep_compact!
8
8
  self.each do |key, val|
9
- case val
10
- when Hash
11
- val = val.deep_compact!
12
- self.delete(key) if val.blank?
13
- when Array
14
- val = val.deep_compact!
15
- self.delete(key) if val.blank?
16
- when String
17
- self.delete(key) if val.blank?
18
- when nil
19
- self.delete(key)
20
- end
9
+ val.deep_compact! if val.respond_to?(:deep_compact!)
10
+ self.delete(key) if val.blank?
21
11
  end
22
- self.blank? ? nil : self
12
+ self
23
13
  end
24
14
  end
@@ -5,7 +5,7 @@ require 'logger'
5
5
  #
6
6
  # define Log yourself to prevent its creation
7
7
  #
8
- ::Log = Logger.new(STDERR) unless defined?(::Log)
8
+ ::Log = Logger.new($stderr) unless defined?(::Log)
9
9
 
10
10
  def Log.dump *args
11
11
  debug args.map(&:inspect).join("\t")
@@ -1,4 +1,13 @@
1
1
  Numeric.class_eval do
2
+ #
3
+ # Coerce a number to lie between min and max.
4
+ #
5
+ # @example
6
+ # 5.clamp(6, 7) # => 6
7
+ # 5.clamp(6) # => 6
8
+ # 5.clamp(nil, 6) # => 5
9
+ # 5.clamp(nil, 4) # => 4
10
+ #
2
11
  def clamp min=nil, max=nil
3
12
  raise ArgumentError, "min must be <= max" if (min && max && (min > max))
4
13
  return min if min && (self < min)
@@ -0,0 +1,10 @@
1
+ class Object
2
+ # @person ? @person.name : nil
3
+ # vs
4
+ # @person.try(:name)
5
+ def try(method)
6
+ send method if respond_to? method
7
+ end
8
+
9
+ end
10
+
@@ -0,0 +1,44 @@
1
+ class Object
2
+ # Override this in a child if it cannot be dup'ed
3
+ #
4
+ # @return [Object]
5
+ def try_dup
6
+ self.dup
7
+ end
8
+ end
9
+
10
+ class TrueClass
11
+ def try_dup
12
+ self
13
+ end
14
+ end
15
+
16
+ class FalseClass
17
+ def try_dup
18
+ self
19
+ end
20
+ end
21
+
22
+ class Module
23
+ def try_dup
24
+ self
25
+ end
26
+ end
27
+
28
+ class NilClass
29
+ def try_dup
30
+ self
31
+ end
32
+ end
33
+
34
+ class Numeric
35
+ def try_dup
36
+ self
37
+ end
38
+ end
39
+
40
+ class Symbol
41
+ def try_dup
42
+ self
43
+ end
44
+ end
@@ -34,9 +34,7 @@ class Array
34
34
  default_words_connector = ", "
35
35
  default_two_words_connector = " and "
36
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
37
+ options = { :words_connector => default_words_connector, :two_words_connector => default_two_words_connector, :last_word_connector => default_last_word_connector }.merge(options)
40
38
 
41
39
  case length
42
40
  when 0
@@ -16,13 +16,13 @@ class String
16
16
  # # => "And they f... (continued)"
17
17
  def truncate(length, options = {})
18
18
  text = self.dup
19
- chars = text.respond_to?(:mb_chars) ? text.mb_chars : text.chars
19
+ chars = text.respond_to?(:mb_chars) ? text.mb_chars : text
20
20
  omission = options[:omission] || "..."
21
21
  omission_len = omission.respond_to?(:mb_chars) ? omission.mb_chars.length : omission.length
22
22
  length_with_room_for_omission = length - omission_len
23
23
 
24
24
  if (separator = options[:separator])
25
- separator_chars = separator.respond_to?(:mb_chars) ? separator.to_s.mb_chars : separator.to_s.chars
25
+ separator_chars = separator.respond_to?(:mb_chars) ? separator.to_s.mb_chars : separator.to_s
26
26
  stop = chars.rindex(separator_chars, length_with_room_for_omission) || length_with_room_for_omission
27
27
  else
28
28
  stop = length_with_room_for_omission
@@ -0,0 +1,37 @@
1
+ require File.dirname(__FILE__)+'/../spec_helper'
2
+ require 'gorillib/array/compact_blank'
3
+
4
+ describe Array do
5
+
6
+ describe '#compact_blank' do
7
+ it 'with empty' do
8
+ [ [nil], [nil, false, {}, ""] ].each do |arr|
9
+ arr.compact_blank.should == []
10
+ arr.length.should_not == 0
11
+ end
12
+ end
13
+
14
+ it 'with full' do
15
+ [ [nil, 1, nil, 2], [nil, 1, false, 2, {}, ""] ].each do |arr|
16
+ arr.compact_blank.should == [1, 2]
17
+ end
18
+ end
19
+ end
20
+
21
+ describe '#compact_blank!' do
22
+ it 'with empty' do
23
+ [].compact_blank!.should == []
24
+ [ [nil], [nil, false, {}, ""] ].each do |arr|
25
+ arr.compact_blank!.should == []
26
+ arr.length.should == 0
27
+ end
28
+ end
29
+
30
+ it 'with full' do
31
+ [ [nil, 1, nil, 2], [nil, 1, false, 2, {}, ""] ].each do |arr|
32
+ arr.compact_blank!.should == [1, 2]
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,47 @@
1
+ require File.dirname(__FILE__)+'/../spec_helper'
2
+ require 'gorillib/array/extract_options'
3
+
4
+ class HashSubclass < Hash
5
+ end
6
+
7
+ class ExtractableHashSubclass < Hash
8
+ def extractable_options?
9
+ true
10
+ end
11
+ end
12
+
13
+ describe Array do
14
+ describe '#extract_options!' do
15
+ it 'pulls empty hash from empty array' do
16
+ [].extract_options!.should == {}
17
+ end
18
+ it 'pulls empty hash from array with no hash' do
19
+ [1].extract_options!.should == {}
20
+ end
21
+ it 'pulls hash from array with only that hash' do
22
+ [{:a=>:b}].extract_options!.should == {:a=>:b}
23
+ end
24
+ it 'pulls hash from end of array' do
25
+ [1, {:a=>:b}].extract_options!.should == {:a=>:b}
26
+ end
27
+
28
+ it 'does not extract hash subclasses' do
29
+ hash = HashSubclass.new
30
+ hash[:foo] = 1
31
+ array = [hash]
32
+ options = array.extract_options!
33
+ options.should == {}
34
+ array.should == [hash]
35
+ end
36
+
37
+ it 'does extract extractable subclass' do
38
+ hash = ExtractableHashSubclass.new
39
+ hash[:foo] = 1
40
+ array = [hash]
41
+ options = array.extract_options!
42
+ options.should == {:foo => 1}
43
+ array.should == []
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,38 @@
1
+ require File.dirname(__FILE__)+'/../spec_helper'
2
+ require 'gorillib/datetime/flat'
3
+ require 'gorillib/datetime/parse'
4
+
5
+ describe Time do
6
+ describe '#to_flat' do
7
+ before do
8
+ @time_utc = Time.parse("2011-02-03T04:05:06 UTC")
9
+ @time_cst = Time.parse("2011-02-02T22:05:06-06:00")
10
+ @time_flat = "20110203040506"
11
+ end
12
+
13
+ it 'converts times to UTC' do
14
+ @time_utc.to_flat.should == @time_flat
15
+ @time_cst.to_flat.should == @time_flat
16
+ end
17
+
18
+ it 'round-trips' do
19
+ Time.parse_safely(@time_flat).to_flat.should == @time_flat
20
+ Time.parse_safely(@time_utc.to_flat).should == @time_utc
21
+ end
22
+
23
+ end
24
+ end
25
+
26
+ describe Date do
27
+ describe '#to_flat' do
28
+ before do
29
+ @date = Date.new(2011, 2, 3)
30
+ @date_flat = "20110203"
31
+ end
32
+
33
+ it 'converts dates' do
34
+ @date.to_flat.should == @date_flat
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,48 @@
1
+ require File.dirname(__FILE__)+'/../spec_helper'
2
+ require 'gorillib/datetime/flat'
3
+ require 'gorillib/datetime/parse'
4
+
5
+ describe DateTime do
6
+ describe '#parse_safely' do
7
+ before do
8
+ @time_utc = Time.parse("2011-02-03T04:05:06 UTC")
9
+ @time_cst = Time.parse("2011-02-02T22:05:06-06:00")
10
+ @time_flat = "20110203040506"
11
+ @time_iso_utc = "2011-02-03T04:05:06+00:00"
12
+ @time_iso_cst = "2011-02-02T22:05:06-06:00"
13
+ end
14
+
15
+ it 'with a Time, passes it through.' do
16
+ Time.parse_safely(@time_utc).should == @time_utc
17
+ Time.parse_safely(@time_cst).should == @time_cst
18
+ end
19
+
20
+ it 'with a Time, converts to UTC.' do
21
+ Time.parse_safely(@time_utc).utc_offset.should == 0
22
+ Time.parse_safely(@time_cst).utc_offset.should == 0
23
+ end
24
+
25
+ it 'with a flat time, converts to UTC Time instance' do
26
+ Time.parse_safely(@time_flat).should == @time_utc
27
+ Time.parse_safely(@time_flat).utc_offset.should == 0
28
+ end
29
+
30
+ it 'with a flat time and Z, converts to UTC Time instance' do
31
+ Time.parse_safely(@time_flat+'Z').should == @time_utc
32
+ Time.parse_safely(@time_flat+'Z').utc_offset.should == 0
33
+ end
34
+
35
+ it 'parses a regular time string, converting to UTC' do
36
+ Time.parse_safely(@time_iso_utc).should == @time_utc
37
+ Time.parse_safely(@time_iso_utc).utc_offset.should == 0
38
+ Time.parse_safely(@time_iso_cst).should == @time_utc
39
+ Time.parse_safely(@time_iso_cst).utc_offset.should == 0
40
+ end
41
+
42
+ it 'round-trips' do
43
+ Time.parse_safely(@time_flat).to_flat.should == @time_flat
44
+ Time.parse_safely(@time_utc.to_flat).should == @time_utc
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,56 @@
1
+ require File.dirname(__FILE__)+'/../spec_helper'
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
+ describe Enumerable do
10
+ describe '#sum' do
11
+ it 'sums lists of numbers to a number' do
12
+ [5, 15, 10].sum .should == 30
13
+ [5, 15, 10].sum{|i| i }.should == 30
14
+ end
15
+
16
+ it 'sums list of strings to a string' do
17
+
18
+ %w(a b c).sum .should == 'abc'
19
+ %w(a b c).sum{|i| i }.should == 'abc'
20
+ end
21
+
22
+ it 'sums list of objects with a &:method' do
23
+ payments = [ Payment.new(5), Payment.new(15), Payment.new(10) ]
24
+ payments.sum(&:price) .should == 30
25
+ payments.sum { |p| p.price * 2 }.should == 60
26
+ end
27
+
28
+ it 'sums object with a synthetic "+" method' do
29
+ payments = [ SummablePayment.new(5), SummablePayment.new(15) ]
30
+ payments.sum .should == SummablePayment.new(20)
31
+ payments.sum{|p| p }.should == SummablePayment.new(20)
32
+ end
33
+
34
+ it 'handles nil sums' do
35
+ lambda{ [5, 15, nil].sum }.should raise_error(TypeError)
36
+
37
+ payments = [ Payment.new(5), Payment.new(15), Payment.new(10), Payment.new(nil) ]
38
+ lambda{ payments.sum(&:price) }.should raise_error(TypeError)
39
+ payments.sum{|p| p.price.to_i * 2 }.should == 60
40
+ end
41
+
42
+ it 'handles empty sums' do
43
+ [].sum .should == 0
44
+ [].sum{|i| i }.should == 0
45
+ [].sum(Payment.new(0)).should == Payment.new(0)
46
+ end
47
+
48
+ it 'behaves the same on ranges' do
49
+ (1..4).sum{|i| i * 2 }.should == 20
50
+ (1..4).sum .should == 10
51
+ (1..4.5).sum .should == 10
52
+ (1...4).sum .should == 6
53
+ ('a'..'c').sum .should == 'abc'
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,70 @@
1
+ require File.dirname(__FILE__)+'/../spec_helper'
2
+ require 'gorillib/hash/compact'
3
+
4
+ describe Hash do
5
+ describe '#compact' do
6
+ it 'scrubs nil' do
7
+ hsh = { 1 => nil }
8
+ hsh.compact.should == {}
9
+ hsh.length.should == 1
10
+ end
11
+
12
+ it 'does not scrub false, {} or ""' do
13
+ hsh = { 1 => nil, 2 => false, 3 => {}, 4 => "" }
14
+ hsh.compact.should == { 2 => false, 3 => {}, 4 => "" }
15
+ hsh.length.should == 4
16
+ end
17
+
18
+ it 'with values' do
19
+ { 1 => nil, nil => 2 }.compact.should == { nil => 2 }
20
+ { 1 => nil, 2 => :val_2, 3 => {}, 4 => :val_4}.compact.should == { 2 => :val_2, 3 => {}, 4 => :val_4 }
21
+ end
22
+ end
23
+
24
+ describe '#compact!' do
25
+ it 'scrubs nil' do
26
+ hsh = { 1 => nil }
27
+ hsh.compact!.should == {}
28
+ hsh.length.should == 0
29
+ end
30
+
31
+ it 'does not scrub false, {} or ""' do
32
+ hsh = { 1 => nil, 2 => false, 3 => {}, 4 => "" }
33
+ hsh.compact!.should == { 2 => false, 3 => {}, 4 => "" }
34
+ hsh.length.should == 3
35
+ end
36
+
37
+ it 'with values' do
38
+ { 1 => nil, nil => 2 }.compact!.should == { nil => 2 }
39
+ { 1 => nil, 2 => :val_2, 3 => {}, 4 => :val_4}.compact!.should == { 2 => :val_2, 3 => {}, 4 => :val_4 }
40
+ end
41
+ end
42
+
43
+ describe '#compact_blank' do
44
+ it 'when empty' do
45
+ [ { 1 => nil}, { 1 => nil, 2 => false, 3 => {}, 4 => ""} ].each do |hsh|
46
+ hsh.compact_blank.should == {}
47
+ hsh.length.should_not == 0
48
+ end
49
+ end
50
+
51
+ it 'with values' do
52
+ { 1 => nil, nil => 2 }.compact_blank.should == { nil => 2 }
53
+ { 1 => nil, 2 => :val_2, 3 => {}, 4 => :val_4}.compact_blank.should == { 2 => :val_2, 4 => :val_4 }
54
+ end
55
+ end
56
+
57
+ describe '#compact_blank!' do
58
+ it 'when empty' do
59
+ [ { 1 => nil}, { 1 => nil, 2 => false, 3 => {}, 4 => ""} ].each do |hsh|
60
+ hsh.compact_blank!.should == {}
61
+ hsh.length.should == 0
62
+ end
63
+ end
64
+
65
+ it 'with values' do
66
+ { 1 => nil, nil => 2 }.compact_blank!.should == { nil => 2 }
67
+ { 1 => nil, 2 => :val_2, 3 => {}, 4 => :val_4}.compact_blank!.should == { 2 => :val_2, 4 => :val_4 }
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,37 @@
1
+ require File.dirname(__FILE__)+'/../spec_helper'
2
+ require 'gorillib/hash/deep_compact'
3
+ require 'gorillib/array/deep_compact'
4
+
5
+ describe Hash do
6
+ describe 'array/deep_compact and hash/deep_compact' do
7
+ it "should respond to the method deep_compact!" do
8
+ { }.should respond_to :deep_compact!
9
+ end
10
+
11
+ it "should return nil if all values evaluate as blank" do
12
+ { :a => nil, :b => "", :c => [], :d => {} }.deep_compact!.should == {}
13
+ end
14
+
15
+ it "should return a hash with all blank values removed recursively" do
16
+ @test_hash = {:e=>["", nil, [], {}, "foo", { :a=> [nil, {}, { :c=> ["","",[]] } ], :b => nil }]}
17
+ @test_hash.deep_compact!.should == {:e=>["foo"]}
18
+ end
19
+ end
20
+ end
21
+
22
+ describe Array do
23
+ describe 'array/deep_compact and hash/deep_compact' do
24
+ it "should respond to the method deep_compact!" do
25
+ [ ].should respond_to :deep_compact!
26
+ end
27
+
28
+ it "should return nil if all values evaluate as blank" do
29
+ [nil, '', { }, []].deep_compact!.should == []
30
+ end
31
+
32
+ it "should return a hash with all blank values removed recursively" do
33
+ @test_arr = ["", nil, [], {}, "foo", { :a=> [nil, {}, { :c=> ["","",[]] } ], :b => nil }]
34
+ @test_arr.deep_compact!.should == ["foo"]
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,117 @@
1
+ require File.dirname(__FILE__)+'/../spec_helper'
2
+ require 'gorillib/hash/deep_merge'
3
+
4
+ describe Hash do
5
+ describe '#deep_merge' do
6
+ before do
7
+ @hash_1 =
8
+ { :a => 1, :b => "b", :c => { :val => "val", :arr => ['hi'], :hsh => { :d1 => "d1" } } }
9
+ end
10
+
11
+ it 'merges, replacing values on the left' do
12
+ @hash_1.deep_merge(
13
+ { :a => 1, :c => { :val => 2, } }).should ==
14
+ { :a => 1, :b => "b", :c => { :val => 2, :arr => ['hi'], :hsh => { :d1 => "d1" } } }
15
+ @hash_1.should ==
16
+ { :a => 1, :b => "b", :c => { :val => "val", :arr => ['hi'], :hsh => { :d1 => "d1" } } }
17
+ end
18
+
19
+ it 'merges, merging hashes where they meet' do
20
+ @hash_1.deep_merge(
21
+ { :a => 1, :c => { :val => 2, :hsh => { :d2 => "d2" } } }).should ==
22
+ { :a => 1, :b => "b", :c => { :val => 2, :arr => ['hi'], :hsh => { :d1 => "d1", :d2 => "d2" } } }
23
+ @hash_1.should ==
24
+ { :a => 1, :b => "b", :c => { :val => "val", :arr => ['hi'], :hsh => { :d1 => "d1" } } }
25
+ end
26
+
27
+ it 'merges, replacing hash on left with value on right' do
28
+ @hash_1.deep_merge(
29
+ { :a => 1, :c => { :hsh => :val } }).should ==
30
+ { :a => 1, :b => "b", :c => { :val => "val", :arr => ['hi'], :hsh => :val } }
31
+ @hash_1.should ==
32
+ { :a => 1, :b => "b", :c => { :val => "val", :arr => ['hi'], :hsh => { :d1 => "d1" } } }
33
+ end
34
+
35
+ it 'merges, replacing val on left with hash on right' do
36
+ @hash_1.deep_merge(
37
+ { :a => 1, :c => { :val => {}, } }).should ==
38
+ { :a => 1, :b => "b", :c => { :val => {}, :arr => ['hi'], :hsh => { :d1 => "d1" } } }
39
+ @hash_1.should ==
40
+ { :a => 1, :b => "b", :c => { :val => "val", :arr => ['hi'], :hsh => { :d1 => "d1" } } }
41
+ end
42
+
43
+ it 'merges, replacing array on left with array on right without merging' do
44
+ @hash_1.deep_merge(
45
+ { :a => 1, :c => { :arr => ['whatevs'] } }).should ==
46
+ { :a => 1, :b => "b", :c => { :val => "val", :arr => ['whatevs'], :hsh => { :d1 => "d1" } } }
47
+ @hash_1.should ==
48
+ { :a => 1, :b => "b", :c => { :val => "val", :arr => ['hi'], :hsh => { :d1 => "d1" } } }
49
+ end
50
+ end
51
+
52
+ describe '#deep_merge!' do
53
+ before do
54
+ @hash_1 = {
55
+ :a => 1, :b => "b", :c => { :val => "val", :arr => ['hi'], :hsh => { :d1 => "d1" } } }
56
+ end
57
+
58
+ it 'merges, replacing values on the left' do
59
+ @hash_1.deep_merge!(
60
+ { :a => 1, :c => { :val => 2, } }).should ==
61
+ { :a => 1, :b => "b", :c => { :val => 2, :arr => ['hi'], :hsh => { :d1 => "d1" } } }
62
+ @hash_1.should ==
63
+ { :a => 1, :b => "b", :c => { :val => 2, :arr => ['hi'], :hsh => { :d1 => "d1" } } }
64
+ end
65
+
66
+ it 'merges, merging hashes where they meet' do
67
+ @hash_1.deep_merge!(
68
+ { :a => 1, :c => { :val => 2, :hsh => { :d2 => "d2" } } }).should ==
69
+ { :a => 1, :b => "b", :c => { :val => 2, :arr => ['hi'], :hsh => { :d1 => "d1", :d2 => "d2" } } }
70
+ @hash_1.should ==
71
+ { :a => 1, :b => "b", :c => { :val => 2, :arr => ['hi'], :hsh => { :d1 => "d1", :d2 => "d2" } } }
72
+ end
73
+
74
+ it 'merges, replacing hash on left with value on right' do
75
+ @hash_1.deep_merge!(
76
+ { :a => 1, :c => { :hsh => :val } }).should ==
77
+ { :a => 1, :b => "b", :c => { :val => "val", :arr => ['hi'], :hsh => :val } }
78
+ @hash_1.should ==
79
+ { :a => 1, :b => "b", :c => { :val => "val", :arr => ['hi'], :hsh => :val } }
80
+ end
81
+
82
+ it 'merges, replacing val on left with hash on right' do
83
+ @hash_1.deep_merge!(
84
+ { :a => 1, :c => { :val => {}, } }).should ==
85
+ { :a => 1, :b => "b", :c => { :val => {}, :arr => ['hi'], :hsh => { :d1 => "d1" } } }
86
+ @hash_1.should ==
87
+ { :a => 1, :b => "b", :c => { :val => {}, :arr => ['hi'], :hsh => { :d1 => "d1" } } }
88
+ end
89
+
90
+ it 'merges, replacing array on left with array on right without merging' do
91
+ @hash_1.deep_merge!(
92
+ { :a => 1, :c => { :arr => ['whatevs'] } }).should ==
93
+ { :a => 1, :b => "b", :c => { :val => "val", :arr => ['whatevs'], :hsh => { :d1 => "d1" } } }
94
+ @hash_1.should ==
95
+ { :a => 1, :b => "b", :c => { :val => "val", :arr => ['whatevs'], :hsh => { :d1 => "d1" } } }
96
+ end
97
+ end
98
+
99
+
100
+
101
+ describe '#deep_dup' do
102
+ # def test_deep_dup
103
+ # hash = { :a => { :b => 'b' } }
104
+ # dup = hash.deep_dup
105
+ # dup[:a][:c] = 'c'
106
+ # assert_equal nil, hash[:a][:c]
107
+ # assert_equal 'c', dup[:a][:c]
108
+ # end
109
+ #
110
+ # def test_deep_dup_initialize
111
+ # zero_hash = Hash.new 0
112
+ # hash = { :a => zero_hash }
113
+ # dup = hash.deep_dup
114
+ # assert_equal 0, dup[:a][44]
115
+ # end
116
+ end
117
+ end