angry_hash 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.0.4
data/angry_hash.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{angry_hash}
8
- s.version = "0.0.3"
8
+ s.version = "0.0.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Lachie Cox"]
12
- s.date = %q{2010-04-29}
12
+ s.date = %q{2010-05-19}
13
13
  s.description = %q{A stabler mash with different emphases. Used in plus2 projects AngryMob and Igor.}
14
14
  s.email = %q{lachie@plus2.com.au}
15
15
  s.files = [
@@ -17,8 +17,11 @@ Gem::Specification.new do |s|
17
17
  "Rakefile",
18
18
  "VERSION",
19
19
  "angry_hash.gemspec",
20
+ "examples/accessors_eg.rb",
20
21
  "examples/creation_eg.rb",
22
+ "examples/dup_eg.rb",
21
23
  "examples/eg_helper.rb",
24
+ "examples/merge_eg.rb",
22
25
  "lib/angry_hash.rb",
23
26
  "lib/angry_hash/merge_string.rb"
24
27
  ]
@@ -0,0 +1,35 @@
1
+ require 'eg_helper'
2
+
3
+ eg.setup do
4
+ @a = AngryHash[
5
+ :b => {
6
+ :c => 'c',
7
+ :d => 'd'
8
+ }
9
+ ]
10
+ end
11
+
12
+ def same_obj(a,b)
13
+ a.__id__ == b.__id__
14
+ end
15
+
16
+ eg 'accessor! with existing subhash' do
17
+ Assert( same_obj( @a.b!, @a.b ) )
18
+ end
19
+
20
+ eg 'accessor! creating and returning' do
21
+ d = @a.d!
22
+ Assert( same_obj( d, @a.d ) )
23
+ end
24
+
25
+ eg 'accessor= AngryHash' do
26
+ d = AngryHash.new
27
+ @a.d = d
28
+ Assert( same_obj( d, @a.d ) )
29
+ end
30
+
31
+ eg 'accessor= Hash' do
32
+ d = {}
33
+ @a.d = d
34
+ Assert( ! same_obj( d, @a.d ) )
35
+ end
@@ -24,15 +24,19 @@ eg.helpers do
24
24
  end
25
25
 
26
26
  eg 'creation duplicates' do
27
- a1 = AngryHash[ :a => { :b => 1 }, :c => [ 1, :d, {:e => :f}, nil, true, false, 1.0, [ 'x', 'y' ] ] ]
27
+ a1 = AngryHash[
28
+ :a => { :b => 1 },
29
+ :c => [ 1, :d, {:e => :f}, nil, true, false, 1.0, [ 'x', 'y' ] ]
30
+ ]
28
31
  a2 = AngryHash[ a1 ]
29
32
 
30
33
  pp oids(a1)
31
34
  pp oids(a2)
32
35
 
33
- Check(a1.c[2].__id__ != a2.c[2].__id__).is(true)
34
- Check(a1.c[7].__id__ != a2.c[7].__id__).is(true)
36
+ Assert(a1.a.__id__ != a2.a.__id__)
37
+ Assert(a1.c[2].__id__ != a2.c[2].__id__)
38
+ Assert(a1.c[7].__id__ != a2.c[7].__id__)
35
39
  end
36
40
 
37
- eg 'cycle detection' do
38
- end
41
+ #eg 'cycle detection' do
42
+ #end
@@ -0,0 +1,68 @@
1
+ require 'eg_helper'
2
+
3
+ eg.setup do
4
+ @original = { 'database' => {
5
+ "micropower_micropower_sandbox"=>
6
+ {"app_owner"=>"micropower_micropower_sandbox", "server"=>:db},
7
+ "amc_accred_staging"=>
8
+ {"app_owner"=>"amc_accred", "server"=>:plus2staging_local_mysql},
9
+ "post_froggy"=>
10
+ {"app_owner"=>"froggy_owner",
11
+ "backup"=>{"to_s3"=>true},
12
+ "server"=>:postfrog},
13
+ "isg_url_shortener"=>
14
+ {"app_owner"=>"isg_sandbox_v5", "server"=>:isg_forums_mysql},
15
+ "isg_forums"=>{"app_owner"=>"isg_forums", "server"=>:isg_forums_mysql},
16
+ "eggs_eggs"=>
17
+ {"app_owner"=>"eggs_eggs",
18
+ "backup"=>{"to_s3"=>true},
19
+ "server"=>:db,
20
+ "admin_owner"=>"eggs_admin"},
21
+ "myfrogdb"=>{"app_owner"=>:myfroggy, "server"=>:myfrog},
22
+ "amc_exam_staging"=>
23
+ {"app_owner"=>"amc_exam", "server"=>:plus2staging_local_mysql},
24
+ "micropower_golfo"=>{"app_owner"=>:golfo, "server"=>:linode_golfo_mysql},
25
+ "linode_golfo"=>{"app_owner"=>:golfo, "server"=>:linode_golfo_mysql},
26
+ "halal_staging"=>
27
+ {"app_owner"=>"halal", "server"=>:plus2staging_local_postgres},
28
+ "eggs_enag"=>
29
+ {"app_owner"=>"eggs_enag", "backup"=>{"to_s3"=>true}, "server"=>:db},
30
+ "amc_store"=>
31
+ {"app_owner"=>"amc_store", "backup"=>{"to_s3"=>true}, "server"=>:amc},
32
+ "weatherzone_wengine"=>
33
+ {"app_owner"=>"weatherzone_wengine", "server"=>:linode_postgres},
34
+ "weatherzone_wzfb_staging"=>
35
+ {"app_owner"=>"weatherzone_wzfb_staging", "server"=>:db},
36
+ "amc_ncmr"=>
37
+ {"app_owner"=>"amc_ncmr", "backup"=>{"to_s3"=>true}, "server"=>:amc},
38
+ "westpac_thinkbank_staging"=>
39
+ {"app_owner"=>"westpac_thinkbank_staging", "server"=>:db},
40
+ "micropower_micropower_staging"=>
41
+ {"app_owner"=>"micropower", "server"=>:staging_mysql},
42
+ "weatherzone_wx_staging"=>
43
+ {"app_owner"=>"weatherzone_wx_staging", "server"=>:db},
44
+ "isg_sandbox_v4"=>
45
+ {"app_owner"=>"isg_sandbox_v5", "server"=>:isg_forums_mysql},
46
+ "eggs_aecl"=>
47
+ {"app_owner"=>"eggs_aecl", "backup"=>{"to_s3"=>true}, "server"=>:db},
48
+ "eggs_hwag"=>
49
+ {"app_owner"=>"eggs_hwag", "backup"=>{"to_s3"=>true}, "server"=>:db},
50
+ "plus2_gemcutter"=>{"app_owner"=>"plus2_gemcutter", "server"=>:db},
51
+ "isg_sandbox_v5"=>
52
+ {"app_owner"=>"isg_sandbox_v5", "server"=>:isg_forums_mysql},
53
+ "amc_exam"=>
54
+ {"app_owner"=>"amc_exam", "backup"=>{"to_s3"=>true}, "server"=>:amc},
55
+ "weatherzone_wzfb"=>
56
+ {"app_owner"=>"weatherzone_wzfb", "backup"=>{"to_s3"=>true}, "server"=>:db},
57
+ "amc_store_staging"=>
58
+ {"app_owner"=>"amc_store", "server"=>:plus2staging_local_mysql}
59
+ }}
60
+ end
61
+
62
+ eg 'duping copies symbols' do
63
+ ah = AngryHash[ @original ]
64
+ ah2 = AngryHash[ ah ]
65
+
66
+ Assert( ! ah2.database.isg_sandbox_v5.server.nil? )
67
+ Assert( ah2.database.isg_sandbox_v5.server == @original['database']['isg_sandbox_v5']['server'] )
68
+ end
@@ -1,6 +1,16 @@
1
1
  require 'pathname'
2
2
  root = Pathname('../..').expand_path(__FILE__)
3
3
  require 'pp'
4
+
5
+ UseGem = false
6
+
7
+ if UseGem
8
+ require 'rubygems'
9
+ require 'angry_hash'
10
+ else
11
+ $:.unshift root+'lib'
12
+ require root+'lib/angry_hash'
13
+ end
14
+
15
+ require 'rubygems'
4
16
  require 'exemplor'
5
- $:.unshift root+'lib'
6
- require 'angry_hash'
@@ -0,0 +1,134 @@
1
+ require 'eg_helper'
2
+ require 'yajl'
3
+
4
+ eg.setup do
5
+ @a = AngryHash[
6
+ :b => {
7
+ :c => 'c',
8
+ :d => 'd'
9
+ }
10
+ ]
11
+
12
+ @b = AngryHash[
13
+ :b => {
14
+ :d => 'dd',
15
+ :e => 'e'
16
+ }
17
+ ]
18
+ end
19
+
20
+ def same_obj(a,b)
21
+ a.__id__ == b.__id__
22
+ end
23
+
24
+ eg 'merges' do
25
+ merged = @a.merge(@b)
26
+
27
+ Assert( ! same_obj( merged, @a ) )
28
+ Assert( ! same_obj( merged, @b ) )
29
+
30
+ Assert( ! merged.b.c? )
31
+ Assert( merged.b.d == 'dd' )
32
+ Assert( merged.b.e == 'e' )
33
+ end
34
+
35
+ eg 'merge dups' do
36
+ a = AngryHash[
37
+ :a => {:b => "cows"}
38
+ ]
39
+ b = AngryHash[
40
+ :a => {:c => "bows"}
41
+ ]
42
+
43
+ merged = a.merge(b)
44
+
45
+ Assert( ! same_obj( merged.a.b, a.a.b ) )
46
+ Assert( same_obj( merged.a.c, b.a.c ) )
47
+ end
48
+
49
+ eg 'updates' do
50
+ merged = @a.update(@b)
51
+
52
+ Assert( same_obj( merged, @a ) )
53
+ Assert( ! same_obj( merged, @b ) )
54
+
55
+ Assert( ! merged.b.c? )
56
+ Assert( merged.b.d == 'dd' )
57
+ Assert( merged.b.e == 'e' )
58
+ end
59
+
60
+ eg 'deep_merge' do
61
+ merged = @a.deep_merge(@b)
62
+
63
+ Show(merged)
64
+
65
+ Assert( ! same_obj( merged, @a ) )
66
+ Assert( ! same_obj( merged, @b ) )
67
+
68
+ Assert( merged.b.c == 'c')
69
+ Assert( merged.b.d == 'dd')
70
+ Assert( merged.b.e == 'e')
71
+ end
72
+
73
+ eg 'deep_update' do
74
+ rv = @a.deep_update(@b)
75
+
76
+ Show(@a)
77
+ Assert( same_obj( rv, @a ) )
78
+ Assert( ! same_obj( @a, @b ) )
79
+
80
+ Assert( ! rv.nil? )
81
+ Assert( @a.b.c == 'c')
82
+ Assert( @a.b.d == 'dd')
83
+ Assert( @a.b.e == 'e')
84
+ end
85
+
86
+ eg 'reverse_deep_merge' do
87
+ merged = @a.reverse_deep_merge(@b)
88
+
89
+ Show(merged)
90
+ Assert( ! merged.nil? )
91
+ Assert( ! same_obj( merged, @a ) )
92
+ Assert( ! same_obj( merged, @b ) )
93
+
94
+ Assert( merged.b.c == 'c')
95
+ Assert( merged.b.d == 'd')
96
+ Assert( merged.b.e == 'e')
97
+ end
98
+
99
+ eg 'deep regression' do
100
+ provider = AngryHash[
101
+ :network => {
102
+ :public => {
103
+ :gateway => '69.164.204.1',
104
+ :netmask => '255.255.255.0'
105
+ },
106
+ :private => {
107
+ :netmask => '255.255.128.0'
108
+ }
109
+ }]
110
+
111
+ server = AngryHash[
112
+ :public_ip => '72.14.191.135',
113
+ :private_ip => '192.168.146.105',
114
+ :network => {
115
+ :public => {:gateway => '72.14.191.1'}
116
+ }]
117
+
118
+ server.provider = provider
119
+ server.network!.reverse_deep_merge!(server.provider.network || {})
120
+
121
+ Show( Yajl::Encoder.encode( server ) )
122
+ end
123
+
124
+ eg 'merge with symbol key' do
125
+ orig = AngryHash[{
126
+ "hosts_db"=>:db,
127
+ "run_list"=>["role[database]"],
128
+ "provider"=>"octopus"
129
+ }]
130
+
131
+ merged = orig.merge(:key=>"db")
132
+
133
+ Assert( merged.keys[1].is_a?(String) )
134
+ end
data/lib/angry_hash.rb CHANGED
@@ -4,25 +4,39 @@ class AngryHash < Hash
4
4
  super(__convert(other))
5
5
  end
6
6
 
7
- alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
8
- alias_method :regular_reader, :[] unless method_defined?(:regular_reader)
7
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
8
+ alias_method :regular_reader, :[] unless method_defined?(:regular_reader)
9
9
  alias_method :regular_update, :update unless method_defined?(:regular_update)
10
10
 
11
11
  def []=(key, value)
12
- regular_writer(__convert_key(key), AngryHash.__convert_value(value))
12
+ regular_writer(__convert_key(key), self.class.__convert_value_without_dup(value))
13
13
  end
14
+
14
15
  def [](key)
15
16
  regular_reader(__convert_key(key))
16
17
  end
17
18
 
18
- def update(other_hash)
19
- other_hash.each_pair { |key, value| self[key] = value }
19
+ def dup_and_store(key,value)
20
+ regular_writer(__convert_key(key), self.class.__convert_value(value))
21
+ end
22
+
23
+ alias_method :regular_merge, :merge unless method_defined?(:regular_merge)
24
+ def merge(hash)
25
+ regular_merge(self.class.__convert_without_dup(hash))
26
+ end
27
+
28
+ def merge!(other_hash)
29
+ other_hash.each_pair { |key, value| dup_and_store(key,value) }
20
30
  self
21
31
  end
22
- alias_method :merge!, :update
32
+ alias_method :update, :merge!
33
+
34
+ def dup
35
+ self.class[ self ]
36
+ end
23
37
 
24
38
  def deep_merge(other_hash)
25
- self.merge(other_hash) do |key, oldval, newval|
39
+ self.regular_merge(other_hash) do |key, oldval, newval|
26
40
  oldval = AngryHash.__convert_value(oldval)
27
41
  newval = AngryHash.__convert_value(newval)
28
42
 
@@ -32,11 +46,20 @@ class AngryHash < Hash
32
46
 
33
47
  def deep_merge!(other_hash)
34
48
  replace(deep_merge(other_hash))
49
+ self
50
+ end
51
+ alias_method :deep_update, :deep_merge!
52
+
53
+ def reverse_deep_merge(other_hash)
54
+ self.class.__convert_value(other_hash).deep_merge(self)
35
55
  end
36
56
 
37
57
  def reverse_deep_merge!(other_hash)
38
- replace(self.class.__convert_value(other_hash).deep_merge(self))
58
+ replace(reverse_deep_merge(other_hash))
59
+ self
39
60
  end
61
+ alias_method :reverse_deep_update, :reverse_deep_merge!
62
+
40
63
 
41
64
 
42
65
  def key?(key)
@@ -93,13 +116,15 @@ class AngryHash < Hash
93
116
 
94
117
  case method_s[-1]
95
118
  when ?=
119
+ #regular_writer(key,args.first)
96
120
  self[ key ] = args.first
97
121
 
98
122
  when ??
99
123
  !! self[key]
100
124
 
101
125
  when ?!
102
- self[key] ||= AngryHash.new
126
+ self[key] = AngryHash.new unless self.key?(key)
127
+ self[key]
103
128
 
104
129
  else
105
130
  self[method_s]
@@ -113,27 +138,82 @@ class AngryHash < Hash
113
138
  Symbol === key ? key.to_s : key
114
139
  end
115
140
 
116
- def self.__convert(hash)
117
- hash.inject(AngryHash.new) do |hash,(k,v)|
118
- hash[__convert_key(k)] = __convert_value(v)
119
- hash
141
+
142
+ # non-duplicating convert
143
+ def self.__convert_without_dup(hash)
144
+ hash.inject(AngryHash.new) do |newhash,(k,v)|
145
+ newhash[__convert_key(k)] = __convert_value_without_dup(v)
146
+ newhash
120
147
  end
121
148
  end
122
149
 
123
- def self.__convert_value(v)
150
+ def self.__convert_value_without_dup(v)
124
151
  v = v.to_hash if v.respond_to?(:to_hash)
125
152
 
126
153
  case v
127
154
  when AngryHash
128
155
  v
129
156
  when Hash
130
- __convert(v)
157
+ __convert_without_dup(v)
131
158
  when Array
132
- v.map {|v| Hash === v ? __convert_value(v) : v}
159
+ v.map {|vv| __convert_value_without_dup(vv)}
133
160
  else
134
161
  v
135
162
  end
136
163
  end
164
+
165
+
166
+ # duplicating convert
167
+ def self.__convert(hash,cycle_watch={})
168
+ new_hash = hash.inject(AngryHash.new) do |hash,(k,v)|
169
+ hash.regular_writer( __convert_key(k), __convert_value(v,cycle_watch) )
170
+ hash
171
+ end
172
+
173
+ #puts "re-extend? #{AngryHash === hash} #{hash.__extending_modules.inspect if (AngryHash === hash)}"
174
+ #if AngryHash === hash && hash.__extended?
175
+ #puts "rex"
176
+ #hash.__extending_modules.each {|mod| puts "rexmod=#{mod}"; new_hash.extend(mod)}
177
+ #end
178
+
179
+ new_hash
180
+ end
181
+
182
+ #def __extending_modules
183
+ #@extending_modules ||= []
184
+ #end
185
+ #def __extended?
186
+ #!__extending_modules.empty?
187
+ #end
188
+ #def extend(mod)
189
+ #puts "extending with #{mod}"
190
+ #__extending_modules << mod
191
+ #puts "extending mods: #{__extending_modules.inspect}"
192
+ #super
193
+ #end
194
+
195
+
196
+
197
+ def self.__convert_value(v,cycle_watch={})
198
+ return if cycle_watch.key?(v.__id__)
199
+
200
+ original_v = v
201
+ v = v.to_hash if v.respond_to?(:to_hash)
202
+
203
+ case v
204
+ when Hash
205
+ cycle_watch[original_v.__id__] = true
206
+ __convert(v,cycle_watch)
207
+ when Array
208
+ cycle_watch[original_v.__id__] = true
209
+ v.map {|vv| __convert_value(vv,cycle_watch)}
210
+ when Fixnum,Symbol,NilClass,TrueClass,FalseClass,Float
211
+ v
212
+ else
213
+ cycle_watch[original_v.__id__] = true
214
+ v.dup
215
+ end
216
+ end
137
217
 
138
218
  end
139
219
 
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 3
9
- version: 0.0.3
8
+ - 4
9
+ version: 0.0.4
10
10
  platform: ruby
11
11
  authors:
12
12
  - Lachie Cox
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-29 00:00:00 +10:00
17
+ date: 2010-05-19 00:00:00 +10:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -31,8 +31,11 @@ files:
31
31
  - Rakefile
32
32
  - VERSION
33
33
  - angry_hash.gemspec
34
+ - examples/accessors_eg.rb
34
35
  - examples/creation_eg.rb
36
+ - examples/dup_eg.rb
35
37
  - examples/eg_helper.rb
38
+ - examples/merge_eg.rb
36
39
  - lib/angry_hash.rb
37
40
  - lib/angry_hash/merge_string.rb
38
41
  has_rdoc: true