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.
- data/lib/hashlib.rb +132 -0
- 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: []
|