hashlib 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/hashlib.rb +132 -0
  2. metadata +63 -0
data/lib/hashlib.rb ADDED
@@ -0,0 +1,132 @@
1
+ class Hash
2
+ def diff(other)
3
+ self.keys.inject({}) do |memo, key|
4
+ unless self[key] == other[key]
5
+ if other[key].is_a?(Hash)
6
+ memo[key] = self[key].diff(other[key])
7
+ else
8
+ memo[key] = [self[key], other[key]]
9
+ end
10
+ end
11
+ memo
12
+ end
13
+ end
14
+
15
+ def get(path, default=nil)
16
+ root = self
17
+
18
+ begin
19
+ if not path.is_a?(Array)
20
+ path = path.strip.scan(/[a-z0-9\@\_\-\+]+(?:\[[^\]]+\])?/).to_a
21
+ end
22
+
23
+ path.each do |p|
24
+ x, key, subfield, subvalue = p.split(/([a-z0-9\@\_\-\+]+)(?:\[([^=]+)(?:=(.+))?\])?/i)
25
+ root = (root[key] rescue nil)
26
+ #puts key, root.inspect
27
+
28
+ if subfield and root.is_a?(Array)
29
+ root.each do |r|
30
+ if r.is_a?(Hash) and r[subfield] and ( (subvalue && r[subfield].to_s == subvalue) || true)
31
+ root = r
32
+ break
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ return root || default
39
+ rescue NoMethodError
40
+ return default
41
+ end
42
+ end
43
+
44
+ def set(path, value)
45
+ if not path.is_a?(Array)
46
+ path = path.strip.split(/[\/\.]/)
47
+ end
48
+ root = self
49
+
50
+ path[0..-2].each do |p|
51
+ root[p] = {} unless root[p].is_a?(Hash)
52
+ root = root[p]
53
+ end
54
+
55
+ if value
56
+ root[path.last] = value
57
+ else
58
+ root.reject!{|k,v| k.to_sym == path.last.to_sym }
59
+ end
60
+
61
+ self
62
+ end
63
+
64
+ def unset(path)
65
+ set(path, nil)
66
+ end
67
+
68
+ def rekey(from, to)
69
+ value = get(from)
70
+ unset(from)
71
+ set(to, value)
72
+ end
73
+
74
+ def join(inner_delimiter, outer_delimiter=nil)
75
+ outer_delimiter = inner_delimiter unless outer_delimiter
76
+ self.to_a.collect{|i| i.join(inner_delimiter) }.join(outer_delimiter)
77
+ end
78
+
79
+ def coalesce(prefix=nil, base=nil, delimiter='_')
80
+ base = self unless base
81
+ rv = {}
82
+
83
+ if base.is_a?(Hash)
84
+ base.each do |k,v|
85
+ if v
86
+ base.coalesce(k,v,delimiter).each do |kk,vv|
87
+ kk = (prefix.to_s+delimiter+kk.to_s) if prefix
88
+ rv[kk.to_s] = vv
89
+ end
90
+ end
91
+ end
92
+ else
93
+ rv[prefix.to_s] = base
94
+ end
95
+
96
+ rv
97
+ end
98
+
99
+ def each_recurse(root=self, path=[], &block)
100
+ root.each do |k,v|
101
+ path << k
102
+
103
+ if v.is_a?(Hash)
104
+ each_recurse(v, path, &block)
105
+ else
106
+ yield(k, v, path)
107
+ end
108
+
109
+ path.pop
110
+ end
111
+ end
112
+
113
+ def compact
114
+ def _is_empty?(i)
115
+ i === nil or (i.is_a?(String) and i.strip.chomp.empty?) or (i.respond_to?(:empty?) and i.empty?)
116
+ end
117
+
118
+ each_recurse do |k,v,path|
119
+ path = path.join('.')
120
+
121
+ if v.is_a?(Array)
122
+ v.reject!{|i| _is_empty?(i) }
123
+ unset(path) if v.empty?
124
+
125
+ else
126
+ unset(path) if _is_empty?(v)
127
+ end
128
+ end
129
+
130
+ self
131
+ end
132
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hashlib
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Gary Hetzel
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-14 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: ! "Hashlib: Utility methods for Ruby Hashes\n========================================\n\nHashlib
15
+ extends the base Ruby Hash class with new methods that offer useful functionality
16
+ for working with hashes, specifically addressing handling of deeply-nested Hashes
17
+ for representing rich object structures.\n\nget\n---\n\nThe get method is used to
18
+ allow for retrieval of a deeply-nested value in a hash structure.\n\nGiven:\n\n```ruby\nconfig
19
+ = {\n :global => {\n :security => {\n :sslroot => '/etc/ssl'\n },\n
20
+ \ :pidfile => '/var/run/example.pid'\n },\n :plugins => ['logger', 'cruncher']\n}\n```\n\nThe
21
+ following statements are equivalent:\n\n```ruby\nconfig.get('global.security.sslroot')\n\n#
22
+ returns the same thing as\n\nconfig[:global][:security][:sslroot]\n```\n\nHowever,
23
+ let's say you attempted to get <code>config[:global][:adapters][:path]</code>. You
24
+ would get a nasty NilError because <code>:adapters</code> doesn't exist. However,
25
+ if you used <code>config.get('global.adapters.path')</code>, the result would just
26
+ be <code>nil</code>. _get_ also takes a second argument that let's you specify
27
+ the default value if the given path is not found. This lets you very easily work
28
+ with rich nested hashes while also specifying sane defaults for missing values.\n\n\nset\n---\n\nThe
29
+ set method is the opposite of get. It creates one or more intermediary hashes along
30
+ a specified path and setting the value for the last component.\n\n```ruby\ny = {}\ny.set('this.is.a.number',
31
+ 4)\n\n# results in\n# {\"this\"=>{\n# \"is\"=>{\n# \"a\"=>{\n# \"number\"=>4\n#
32
+ }}}}\n\n```\n"
33
+ email: garyhetzel@gmail.com
34
+ executables: []
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - lib/hashlib.rb
39
+ homepage: https://github.com/ghetzel/hashlib
40
+ licenses: []
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 1.8.11
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: Useful utility methods for working with Ruby hashes
63
+ test_files: []