angry_hash 0.0.3 → 0.0.4

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/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