hashery 2.1.0 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|