angry_hash 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ .*.sw?
2
+ .DS_Store
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = "angry_hash"
5
+ gemspec.summary = "A stabler mash with different emphases."
6
+ gemspec.description = "A stabler mash with different emphases. Used in plus2 projects AngryMob and Igor."
7
+ gemspec.email = "lachie@plus2.com.au"
8
+ gemspec.homepage = "http://github.com/plus2/angry_hash"
9
+ gemspec.authors = ["Lachie Cox"]
10
+ end
11
+ Jeweler::GemcutterTasks.new
12
+ rescue LoadError
13
+ puts "Jeweler not available. Install it with: gem install jeweler"
14
+ end
15
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,58 @@
1
+ class AngryHash
2
+ module MergeString
3
+ def merge_string(string)
4
+ match,key,op,value = *string.match(/^([\w\.]+)(\+?=)(.*)$/)
5
+
6
+ segments = key.split('.')
7
+
8
+ last_segment = segments[-1]
9
+ parent = fetch_path(segments[0..-2])
10
+
11
+ unless AngryHash === parent
12
+ raise "parent path element (at #{segments[0..-2] * '.'}) must be an AngryHash, not #{parent.class}"
13
+ end
14
+
15
+ target = parent[last_segment]
16
+
17
+ case target
18
+ when Array
19
+ __merge_with_op(target,op, [value].flatten.compact)
20
+ when Hash
21
+ raise "not implemented"
22
+ when String
23
+ __merge_with_op(target,op,value.to_s)
24
+ when NilClass
25
+ parent[last_segment] = value
26
+ else
27
+ end
28
+ end
29
+
30
+ def __merge_with_op(target,op,value)
31
+ case op
32
+ when '='
33
+ target.replace(value)
34
+ when '+='
35
+ target.replace( target + value )
36
+ end
37
+ end
38
+
39
+ def fetch_path(segments)
40
+ segments = segments.dup
41
+ return self if segments.empty?
42
+ ctx = self
43
+
44
+
45
+ location = []
46
+ while segment = segments.shift
47
+ unless AngryHash === ctx
48
+ raise "Path element at #{location * '.'} is #{ctx.class}, not an AngryHash. Can't descend to #{path}"
49
+ end
50
+
51
+ location << segment
52
+ ctx = ctx[segment] ||= AngryHash.new
53
+ end
54
+
55
+ ctx
56
+ end
57
+ end
58
+ end
data/lib/angry_hash.rb ADDED
@@ -0,0 +1,115 @@
1
+ class AngryHash < Hash
2
+ def self.[](other)
3
+ super(__convert(other))
4
+ end
5
+
6
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
7
+ alias_method :regular_reader, :[] unless method_defined?(:regular_reader)
8
+ alias_method :regular_update, :update unless method_defined?(:regular_update)
9
+
10
+ def []=(key, value)
11
+ regular_writer(__convert_key(key), AngryHash.__convert_value(value))
12
+ end
13
+ def [](key)
14
+ regular_reader(__convert_key(key))
15
+ end
16
+
17
+ def update(other_hash)
18
+ other_hash.each_pair { |key, value| self[key] = value }
19
+ self
20
+ end
21
+ alias_method :merge!, :update
22
+
23
+ def deep_merge(other_hash)
24
+ self.merge(other_hash) do |key, oldval, newval|
25
+ oldval = AngryHash.__convert_value(oldval)
26
+ newval = AngryHash.__convert_value(newval)
27
+
28
+ AngryHash === oldval && AngryHash === newval ? oldval.deep_merge(newval) : newval
29
+ end
30
+ end
31
+
32
+ def deep_merge!(other_hash)
33
+ replace(deep_merge(other_hash))
34
+ end
35
+
36
+ def reverse_deep_merge!(other_hash)
37
+ replace(self.class.__convert_value(other_hash).deep_merge(self))
38
+ end
39
+
40
+
41
+ def key?(key)
42
+ super(__convert_key(key))
43
+ end
44
+
45
+ alias_method :include?, :key?
46
+ alias_method :has_key?, :key?
47
+ alias_method :member?, :key?
48
+
49
+ def fetch(key, *extras)
50
+ super(__convert_key(key), *extras)
51
+ end
52
+ def values_at(*indices)
53
+ indices.collect {|key| self[__convert_key(key)]}
54
+ end
55
+
56
+ def delete(key)
57
+ super __convert_key(key)
58
+ end
59
+
60
+ def to_hash
61
+ self
62
+ end
63
+
64
+ def method_missing(method,*args,&blk)
65
+ method_s = method.to_s
66
+
67
+ key = method_s[0..-2]
68
+
69
+ case method_s[-1]
70
+ when ?=
71
+ self[ key ] = args.first
72
+
73
+ when ??
74
+ !! self[key]
75
+
76
+ when ?!
77
+ self[key] ||= AngryHash.new
78
+
79
+ else
80
+ self[method_s]
81
+ end
82
+ end
83
+
84
+ def __convert_key(key)
85
+ Symbol === key ? key.to_s : key
86
+ end
87
+ def self.__convert_key(key)
88
+ Symbol === key ? key.to_s : key
89
+ end
90
+
91
+ def self.__convert(hash)
92
+ hash.inject(AngryHash.new) do |hash,(k,v)|
93
+ hash[__convert_key(k)] = __convert_value(v)
94
+ hash
95
+ end
96
+ end
97
+
98
+ def self.__convert_value(v)
99
+ v = v.to_hash if v.respond_to?(:to_hash)
100
+
101
+ case v
102
+ when AngryHash
103
+ v
104
+ when Hash
105
+ __convert(v)
106
+ when Array
107
+ v.map {|v| Hash === v ? __convert_value(v) : v}
108
+ else
109
+ v
110
+ end
111
+ end
112
+
113
+ end
114
+
115
+
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: angry_hash
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Lachie Cox
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-11 00:00:00 +11:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: A stabler mash with different emphases. Used in plus2 projects AngryMob and Igor.
22
+ email: lachie@plus2.com.au
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - .gitignore
31
+ - Rakefile
32
+ - VERSION
33
+ - lib/angry_hash.rb
34
+ - lib/angry_hash/merge_string.rb
35
+ has_rdoc: true
36
+ homepage: http://github.com/plus2/angry_hash
37
+ licenses: []
38
+
39
+ post_install_message:
40
+ rdoc_options:
41
+ - --charset=UTF-8
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ segments:
49
+ - 0
50
+ version: "0"
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.3.6
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: A stabler mash with different emphases.
65
+ test_files: []
66
+