angry_hash 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+