hashlib 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.
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: []