hashery 2.1.0 → 2.1.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.
- checksums.yaml +7 -0
- data/.index +73 -0
- data/{HISTORY.rdoc → HISTORY.md} +25 -12
- data/LICENSE.txt +18 -21
- data/NOTICE.txt +6 -6
- data/{README.rdoc → README.md} +29 -32
- data/demo/00_introduction.rdoc +6 -0
- data/demo/01_open_hash.rdoc +63 -0
- data/demo/02_query_hash.rdoc +17 -0
- data/demo/03_casting_hash.rdoc +12 -0
- data/demo/04_static_hash.rdoc +20 -0
- data/demo/05_key_hash.rdoc +17 -0
- data/demo/06_open_cascade.rdoc +64 -0
- data/demo/07_fuzzy_hash.rdoc +137 -0
- data/demo/08_propery_hash.rdoc +34 -0
- data/demo/10_association.rdoc +59 -0
- data/demo/applique/ae.rb +2 -0
- data/demo/applique/hashery.rb +3 -0
- data/lib/hashery.yml +50 -53
- data/lib/hashery/open_cascade.rb +4 -0
- data/test/case_open_cascade.rb +12 -0
- metadata +86 -149
- data/.meta +0 -76
- data/DEMO.rdoc +0 -1
- data/alt/hashery/basicobject.rb +0 -1
- data/alt/hashery/castinghash.rb +0 -1
- data/alt/hashery/fuzzyhash.rb +0 -1
- data/alt/hashery/keyhash.rb +0 -1
- data/alt/hashery/linkedlist.rb +0 -1
- data/alt/hashery/lruhash.rb +0 -1
- data/alt/hashery/opencascade.rb +0 -1
- data/alt/hashery/openhash.rb +0 -1
- data/alt/hashery/orderedhash.rb +0 -1
- data/alt/hashery/propertyhash.rb +0 -1
- data/alt/hashery/queryhash.rb +0 -1
- data/alt/hashery/statichash.rb +0 -1
@@ -0,0 +1,17 @@
|
|
1
|
+
= QueryHash
|
2
|
+
|
3
|
+
A QueryHash is a Hash that provides open access much like an OpenHash, but it limits readers
|
4
|
+
to bang and query methods (i.e. method ending in `!` or `?`).
|
5
|
+
|
6
|
+
q = QueryHash.new
|
7
|
+
q.a = 1
|
8
|
+
q.b = 2
|
9
|
+
q.a?.assert == 1
|
10
|
+
q.b?.assert == 2
|
11
|
+
|
12
|
+
By default keys are converted to strings.
|
13
|
+
|
14
|
+
q.assert == { "a"=>1, "b"=>2 }
|
15
|
+
|
16
|
+
A QueryHash is compatible with Ruby's standard Hash in every other respect.
|
17
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
= CastingHash
|
2
|
+
|
3
|
+
A CastingHash is a Hash that allows _casting_ procedures to
|
4
|
+
defined that the keys and values pass through upon assignment.
|
5
|
+
|
6
|
+
c = CastingHash.new
|
7
|
+
c.cast_proc = lambda { |k,v| [k.to_s, v.to_s.upcase] }
|
8
|
+
|
9
|
+
c[:a] = 'a'
|
10
|
+
|
11
|
+
c.assert == {'a'=>'A'}
|
12
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
= StaticHash
|
2
|
+
|
3
|
+
A StaticHash is simply a Hash that can only be assigned
|
4
|
+
once per key. Once assigned a subsequent attempt to assign
|
5
|
+
a value to the same key will raise an ArgumentError.
|
6
|
+
|
7
|
+
h = StaticHash.new
|
8
|
+
|
9
|
+
h["x"] = 1
|
10
|
+
|
11
|
+
expect ArgumentError do
|
12
|
+
h["x"] = 2
|
13
|
+
end
|
14
|
+
|
15
|
+
The same error will be raised when using #update or #merge!.
|
16
|
+
|
17
|
+
expect ArgumentError do
|
18
|
+
h.update( "x"=>3 )
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
= KeyHash
|
2
|
+
|
3
|
+
The KeyHash is essentially the same as regular Hash but instead
|
4
|
+
of a `default_proc` the initializer takes the `key_proc` for
|
5
|
+
normalizing keys.
|
6
|
+
|
7
|
+
kh = KeyHash.new{ |k| k.to_s.upcase }
|
8
|
+
kh[:a] = 1
|
9
|
+
kh.to_h #=> ({'A'=>1})
|
10
|
+
|
11
|
+
By default, when no `key_proc` is given, it converts all keys to strings.
|
12
|
+
|
13
|
+
kh = KeyHash.new
|
14
|
+
kh[:a] = 1
|
15
|
+
kh.to_h #=> ({'a'=>1})
|
16
|
+
|
17
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
= OpenCascade
|
2
|
+
|
3
|
+
The reason this class is labeled "cascade", is that every internal
|
4
|
+
Hash is transformed into an OpenCascade dynamically upon access.
|
5
|
+
This makes it easy to create _cascading_ references.
|
6
|
+
|
7
|
+
h = { :x => { :y => { :z => 1 } } }
|
8
|
+
c = OpenCascade[h]
|
9
|
+
assert c.x.y.z == 1
|
10
|
+
|
11
|
+
As soon as you access a node it automatically becomes an OpenCascade.
|
12
|
+
|
13
|
+
c = OpenCascade.new
|
14
|
+
assert(OpenCascade === c.r)
|
15
|
+
assert(OpenCascade === c.a.b)
|
16
|
+
|
17
|
+
But if you set a node, then that will be it's value.
|
18
|
+
|
19
|
+
c.a.b = 4
|
20
|
+
assert c.a.b == 4
|
21
|
+
|
22
|
+
To query a node without causing the auto-creation of an OpenCasade
|
23
|
+
object, use the ?-mark.
|
24
|
+
|
25
|
+
assert c.a.z? == nil
|
26
|
+
|
27
|
+
OpenCascade also transforms Hashes within Arrays.
|
28
|
+
|
29
|
+
h = { :x=>[ {:a=>1}, {:a=>2} ], :y=>1 }
|
30
|
+
c = OpenCascade[h]
|
31
|
+
assert c.x.first.a == 1
|
32
|
+
assert c.x.last.a == 2
|
33
|
+
|
34
|
+
Like OpenObject, OpenCascade allows you to insert entries as array
|
35
|
+
pairs.
|
36
|
+
|
37
|
+
c = OpenCascade.new
|
38
|
+
c << [:x,8]
|
39
|
+
c << [:y,9]
|
40
|
+
|
41
|
+
assert c.x == 8
|
42
|
+
assert c.y == 9
|
43
|
+
|
44
|
+
Finally, you can call methods ending in a !-mark to access the
|
45
|
+
underlying hash (Note that these differ in behavior from the
|
46
|
+
built-in !-methods).
|
47
|
+
|
48
|
+
bk = c.map!{ |k,v| k.to_s.upcase }
|
49
|
+
bk.sort.assert == ['X', 'Y']
|
50
|
+
|
51
|
+
So you can see that for the most an OpenCascade is just like
|
52
|
+
OpenHash, but it allows us to conveniently build open sub-layers
|
53
|
+
easily.
|
54
|
+
|
55
|
+
Enumerable still works with OpenCascades too.
|
56
|
+
|
57
|
+
h = {}
|
58
|
+
c = OpenCascade[:a=>1,:b=>{:c=>3}]
|
59
|
+
c.each do |k,v|
|
60
|
+
h[k] = v
|
61
|
+
end
|
62
|
+
OpenCascade.assert === h[:b]
|
63
|
+
|
64
|
+
|
@@ -0,0 +1,137 @@
|
|
1
|
+
= FuzzyHash
|
2
|
+
|
3
|
+
Should accept strings and retrieve based on them.
|
4
|
+
|
5
|
+
l = FuzzyHash.new
|
6
|
+
l['asd'] = 'qwe'
|
7
|
+
l['asd'].should == 'qwe'
|
8
|
+
|
9
|
+
Should accept strings, but the second time you set the same string, it should overwrite.
|
10
|
+
|
11
|
+
l = FuzzyHash.new
|
12
|
+
l['asd'] = 'asd'
|
13
|
+
l['asd'] = 'qwe'
|
14
|
+
l['asd'].should == 'qwe'
|
15
|
+
|
16
|
+
Should accept regexs too.
|
17
|
+
|
18
|
+
l = FuzzyHash.new
|
19
|
+
l[/asd.*/] = 'qwe'
|
20
|
+
l['asdqweasd'].should == 'qwe'
|
21
|
+
|
22
|
+
Should accept regexs too, but the second time you set the same regex, it should overwrite.
|
23
|
+
|
24
|
+
l = FuzzyHash.new
|
25
|
+
l[/asd/] = 'asd'
|
26
|
+
l[/asd/] = 'qwe'
|
27
|
+
l['asdqweasd'].should == 'qwe'
|
28
|
+
|
29
|
+
Should accept regexs too with the match.
|
30
|
+
|
31
|
+
l = FuzzyHash.new
|
32
|
+
l[/asd.*/] = 'qwe'
|
33
|
+
l.match_with_result('asdqweasd').should == ['qwe', 'asdqweasd']
|
34
|
+
|
35
|
+
Should accept regexs that match the whole strong too with the match.
|
36
|
+
|
37
|
+
l = FuzzyHash.new
|
38
|
+
l[/asd/] = 'qwe'
|
39
|
+
l.match_with_result('asd').should == ['qwe', 'asd']
|
40
|
+
|
41
|
+
Should prefer string to regex matches.
|
42
|
+
|
43
|
+
l = FuzzyHash.new
|
44
|
+
l['asd'] = 'qwe2'
|
45
|
+
l[/asd.*/] = 'qwe'
|
46
|
+
l['asd'].should == 'qwe2'
|
47
|
+
|
48
|
+
Should allow nil keys.
|
49
|
+
|
50
|
+
l = FuzzyHash.new
|
51
|
+
l[nil] = 'qwe2'
|
52
|
+
l['asd'] = 'qwe'
|
53
|
+
l['asd'].should == 'qwe'
|
54
|
+
l[nil].should == 'qwe2'
|
55
|
+
|
56
|
+
Should allow boolean keys.
|
57
|
+
|
58
|
+
l = FuzzyHash.new
|
59
|
+
l[false] = 'false'
|
60
|
+
l[true] = 'true'
|
61
|
+
l[/.*/] = 'everything else'
|
62
|
+
l[true].should == 'true'
|
63
|
+
l[false].should == 'false'
|
64
|
+
l['false'].should == 'everything else'
|
65
|
+
|
66
|
+
Should pick between the correct regex.
|
67
|
+
|
68
|
+
hash = FuzzyHash.new
|
69
|
+
hash[/^\d+$/] = 'number'
|
70
|
+
hash[/.*/] = 'something'
|
71
|
+
hash['123asd'].should == 'something'
|
72
|
+
|
73
|
+
Should be able to delete by value for hash.
|
74
|
+
|
75
|
+
l = FuzzyHash.new
|
76
|
+
l[nil] = 'qwe2'
|
77
|
+
l['asd'] = 'qwe'
|
78
|
+
l['asd'].should == 'qwe'
|
79
|
+
l[nil].should == 'qwe2'
|
80
|
+
l.delete_value('qwe2')
|
81
|
+
l[nil].should == nil
|
82
|
+
|
83
|
+
Should be able to delete by value for regex.
|
84
|
+
|
85
|
+
l = FuzzyHash.new
|
86
|
+
l[/qwe.*/] = 'qwe2'
|
87
|
+
l['asd'] = 'qwe'
|
88
|
+
l['asd'].should == 'qwe'
|
89
|
+
l['qweasd'].should == 'qwe2'
|
90
|
+
l.delete_value('qwe2')
|
91
|
+
l['qweasd'].should == nil
|
92
|
+
|
93
|
+
Should iterate through the keys.
|
94
|
+
|
95
|
+
l = FuzzyHash.new
|
96
|
+
l[/qwe.*/] = 'qwe2'
|
97
|
+
l['asd'] = 'qwe'
|
98
|
+
l['zxc'] = 'qwe'
|
99
|
+
l.keys.size.should == 3
|
100
|
+
|
101
|
+
Should iterate through the values.
|
102
|
+
|
103
|
+
l = FuzzyHash.new
|
104
|
+
l[/qwe.*/] = 'qwe2'
|
105
|
+
l['asd'] = 'qwe'
|
106
|
+
l['zxc'] = 'qwelkj'
|
107
|
+
(['qwe2','qwe','qwelkj'] & l.values).size.should == 3
|
108
|
+
|
109
|
+
Should clear.
|
110
|
+
|
111
|
+
l = FuzzyHash.new
|
112
|
+
l[/qwe.*/] = 'qwe2'
|
113
|
+
l['asd'] = 'qwe'
|
114
|
+
l['zxc'] = 'qwelkj'
|
115
|
+
l.clear
|
116
|
+
l.empty?.should == true
|
117
|
+
|
118
|
+
Should handle equality.
|
119
|
+
|
120
|
+
l_1 = FuzzyHash.new
|
121
|
+
l_1[/qwe.*/] = 'qwe2'
|
122
|
+
l_1['asd'] = 'qwelkj'
|
123
|
+
l_1['zxc'] = 'qwe'
|
124
|
+
l_2 = FuzzyHash.new
|
125
|
+
l_2['zxc'] = 'qwe'
|
126
|
+
l_2['asd'] = 'qwelkj'
|
127
|
+
l_2[/qwe.*/] = 'qwe2'
|
128
|
+
l_1.should == l_2
|
129
|
+
|
130
|
+
Should return the value when adding the value.
|
131
|
+
|
132
|
+
h = FuzzyHash.new
|
133
|
+
(h[/asd/] = '123').should == '123'
|
134
|
+
(h['qwe'] = '123').should == '123'
|
135
|
+
|
136
|
+
That's It.
|
137
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
= PropertyHash
|
2
|
+
|
3
|
+
The Property hash can be used an object in itself.
|
4
|
+
|
5
|
+
h = PropertyHash.new(:a=>1, :b=>2)
|
6
|
+
h[:a] #=> 1
|
7
|
+
h[:a] = 3
|
8
|
+
h[:a] #=> 3
|
9
|
+
|
10
|
+
Becuase the properties are fixed, if we try to set a key that is not present,
|
11
|
+
then we will get an error.
|
12
|
+
|
13
|
+
expect ArgumentError do
|
14
|
+
h[:x] = 5
|
15
|
+
end
|
16
|
+
|
17
|
+
The PropertyHash can also be used as a superclass.
|
18
|
+
|
19
|
+
class MyPropertyHash < PropertyHash
|
20
|
+
property :a, :default => 1
|
21
|
+
property :b, :default => 2
|
22
|
+
end
|
23
|
+
|
24
|
+
h = MyPropertyHash.new
|
25
|
+
h[:a] #=> 1
|
26
|
+
h[:a] = 3
|
27
|
+
h[:a] #=> 3
|
28
|
+
|
29
|
+
Again, if we try to set key that was not fixed, then we will get an error.
|
30
|
+
|
31
|
+
expect ArgumentError do
|
32
|
+
h[:x] = 5
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
= Association
|
2
|
+
|
3
|
+
An Association is a class for creating simple pairings.
|
4
|
+
|
5
|
+
require 'hashery/association'
|
6
|
+
|
7
|
+
An Association can bew created through the usual means
|
8
|
+
of instantiation.
|
9
|
+
|
10
|
+
Association.new(:a, :b)
|
11
|
+
|
12
|
+
Or the shortcut method #>> can be used in most cases.
|
13
|
+
|
14
|
+
:x >> :z
|
15
|
+
|
16
|
+
An association provides two methods to access its content, #index and #value.
|
17
|
+
|
18
|
+
a = 'foo' >> 'bar'
|
19
|
+
|
20
|
+
a.index.assert == 'foo'
|
21
|
+
a.value.assert == 'bar'
|
22
|
+
|
23
|
+
Associations can be used to create ordered-hashes via normal
|
24
|
+
arrays.
|
25
|
+
|
26
|
+
keys = []
|
27
|
+
vals = []
|
28
|
+
|
29
|
+
ohash = [ 'A' >> '3', 'B' >> '2', 'C' >> '1' ]
|
30
|
+
|
31
|
+
ohash.each{ |k,v| keys << k ; vals << v }
|
32
|
+
|
33
|
+
keys.assert == ['A','B','C']
|
34
|
+
vals.assert == ['3','2','1']
|
35
|
+
|
36
|
+
|
37
|
+
Becuase Associations are objects in themselves more complex
|
38
|
+
collections can also be created.
|
39
|
+
|
40
|
+
complex = [
|
41
|
+
'parent' >> 'child',
|
42
|
+
'childless',
|
43
|
+
'another_parent' >> [
|
44
|
+
'subchildless',
|
45
|
+
'subparent' >> 'subchild'
|
46
|
+
]
|
47
|
+
]
|
48
|
+
|
49
|
+
An experimental feature of Association keeps a cache of all defined associations.
|
50
|
+
|
51
|
+
o = Object.new
|
52
|
+
o >> :a
|
53
|
+
o >> :b
|
54
|
+
o >> :c
|
55
|
+
|
56
|
+
o.associations.assert == [:a, :b, :c]
|
57
|
+
|
58
|
+
However this feature will probably be deprecated.
|
59
|
+
|
data/demo/applique/ae.rb
ADDED
data/lib/hashery.yml
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
|
2
|
+
revision: 2013
|
3
|
+
type: ruby
|
4
|
+
sources:
|
5
|
+
- Index.yml
|
6
|
+
- Gemfile
|
4
7
|
authors:
|
5
8
|
- name: Trans
|
6
9
|
email: transfire@gmail.com
|
@@ -10,67 +13,61 @@ authors:
|
|
10
13
|
- name: George Moschovitis
|
11
14
|
- name: Jeena Paradies
|
12
15
|
- name: Erik Veenstra
|
13
|
-
|
14
|
-
-
|
15
|
-
year: '2010'
|
16
|
-
license: BSD-2-Clause
|
16
|
+
organizations:
|
17
|
+
- name: RubyWorks (http://rubyworks.github.com/)
|
17
18
|
requirements:
|
18
|
-
-
|
19
|
-
|
20
|
-
- build
|
21
|
-
development: true
|
22
|
-
- name: qed
|
23
|
-
groups:
|
19
|
+
- groups:
|
20
|
+
- development
|
24
21
|
- test
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
version: '>= 0'
|
23
|
+
name: qed
|
24
|
+
- groups:
|
25
|
+
- development
|
28
26
|
- test
|
29
|
-
|
30
|
-
|
31
|
-
alternatives: []
|
27
|
+
version: '>= 0'
|
28
|
+
name: lemon
|
32
29
|
conflicts: []
|
33
|
-
|
34
|
-
- uri: git://github.com/rubyworks/hashery.git
|
35
|
-
scm: git
|
36
|
-
name: upstream
|
30
|
+
alternatives: []
|
37
31
|
resources:
|
38
|
-
-
|
39
|
-
|
40
|
-
|
41
|
-
-
|
32
|
+
- type: home
|
33
|
+
uri: http://rubyworks.github.com/hashery
|
34
|
+
label: Homepage
|
35
|
+
- type: code
|
36
|
+
uri: http://github.com/rubyworks/hashery
|
42
37
|
label: Source Code
|
43
|
-
|
44
|
-
|
38
|
+
- type: mail
|
39
|
+
uri: http://groups.google.com/group/rubyworks-mailinglist
|
45
40
|
label: Mailing List
|
46
|
-
|
47
|
-
|
41
|
+
- type: docs
|
42
|
+
uri: http://rubydoc.info/github/rubyworks/hashery/master/frames
|
48
43
|
label: Documentation
|
49
|
-
|
50
|
-
|
44
|
+
- type: wiki
|
45
|
+
uri: http://wiki.github.com/rubyworks/hashery
|
51
46
|
label: User Guide
|
52
|
-
|
53
|
-
|
54
|
-
|
47
|
+
- type: gems
|
48
|
+
uri: http://rubygems.org/gems/hashery
|
49
|
+
repositories:
|
50
|
+
- name: upstream
|
51
|
+
scm: git
|
52
|
+
uri: git://github.com/rubyworks/hashery.git
|
55
53
|
categories: []
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
-
|
60
|
-
|
54
|
+
copyrights:
|
55
|
+
- holder: Rubyworks
|
56
|
+
year: '2010'
|
57
|
+
license: BSD-2-Clause
|
58
|
+
customs: []
|
59
|
+
paths:
|
60
|
+
lib:
|
61
|
+
- lib
|
62
|
+
- alt
|
61
63
|
name: hashery
|
62
64
|
title: Hashery
|
63
|
-
|
65
|
+
version: 2.1.1
|
64
66
|
summary: Facets-bread collection of Hash-like classes.
|
65
|
-
description:
|
66
|
-
its many
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
of the CRUDHash which defines a CRUD model on top of Ruby''s standard Hash
|
73
|
-
|
74
|
-
making it a snap to subclass and augment to fit any specific use case.'
|
75
|
-
version: 2.1.0
|
76
|
-
date: '2012-11-24'
|
67
|
+
description: The Hashery is a tight collection of Hash-like classes. Included among
|
68
|
+
its many offerings are the auto-sorting Dictionary class, the efficient LRUHash,
|
69
|
+
the flexible OpenHash and the convenient KeyHash. Nearly every class is a subclass
|
70
|
+
of the CRUDHash which defines a CRUD model on top of Ruby's standard Hash making
|
71
|
+
it a snap to subclass and augment to fit any specific use case.
|
72
|
+
created: '2010-04-21'
|
73
|
+
date: '2013-08-21'
|