hashery 1.5.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/.ruby +30 -17
  2. data/.yardopts +1 -0
  3. data/Config.rb +28 -0
  4. data/{QED.rdoc → DEMO.rdoc} +0 -0
  5. data/HISTORY.rdoc +37 -0
  6. data/LICENSE.txt +26 -0
  7. data/NOTICE.txt +46 -0
  8. data/README.rdoc +10 -7
  9. data/lib/hashery.rb +6 -6
  10. data/lib/hashery.yml +30 -17
  11. data/lib/hashery/association.rb +169 -109
  12. data/lib/hashery/casting_hash.rb +128 -135
  13. data/lib/hashery/core_ext.rb +89 -61
  14. data/lib/hashery/crud_hash.rb +365 -0
  15. data/lib/hashery/dictionary.rb +545 -345
  16. data/lib/hashery/fuzzy_hash.rb +177 -125
  17. data/lib/hashery/ini_hash.rb +321 -0
  18. data/lib/hashery/key_hash.rb +54 -179
  19. data/lib/hashery/linked_list.rb +245 -191
  20. data/lib/hashery/lru_hash.rb +292 -202
  21. data/lib/hashery/open_cascade.rb +133 -78
  22. data/lib/hashery/open_hash.rb +127 -61
  23. data/lib/hashery/ordered_hash.rb +128 -122
  24. data/lib/hashery/path_hash.rb +238 -0
  25. data/lib/hashery/property_hash.rb +144 -80
  26. data/lib/hashery/query_hash.rb +85 -29
  27. data/lib/hashery/stash.rb +7 -3
  28. data/lib/hashery/static_hash.rb +46 -41
  29. data/test/case_association.rb +65 -4
  30. data/test/case_dictionary.rb +149 -5
  31. data/test/{case_keyhash.rb → case_key_hash.rb} +20 -14
  32. data/test/case_lru_hash.rb +162 -0
  33. data/test/{case_opencascade.rb → case_open_cascade.rb} +4 -8
  34. data/test/case_open_hash.rb +87 -0
  35. data/test/case_query_hash.rb +226 -0
  36. data/test/helper.rb +8 -0
  37. metadata +33 -63
  38. data/COPYING.rdoc +0 -45
  39. data/lib/hashery/basic_object.rb +0 -74
  40. data/lib/hashery/basic_struct.rb +0 -288
  41. data/lib/hashery/basicobject.rb +0 -1
  42. data/lib/hashery/basicstruct.rb +0 -1
  43. data/lib/hashery/castinghash.rb +0 -1
  44. data/lib/hashery/fuzzyhash.rb +0 -1
  45. data/lib/hashery/ini.rb +0 -268
  46. data/lib/hashery/keyhash.rb +0 -1
  47. data/lib/hashery/linkedlist.rb +0 -1
  48. data/lib/hashery/lruhash.rb +0 -1
  49. data/lib/hashery/memoizer.rb +0 -64
  50. data/lib/hashery/open_object.rb +0 -1
  51. data/lib/hashery/opencascade.rb +0 -1
  52. data/lib/hashery/openhash.rb +0 -1
  53. data/lib/hashery/openobject.rb +0 -1
  54. data/lib/hashery/orderedhash.rb +0 -1
  55. data/lib/hashery/ostructable.rb +0 -186
  56. data/lib/hashery/propertyhash.rb +0 -1
  57. data/lib/hashery/queryhash.rb +0 -1
  58. data/lib/hashery/statichash.rb +0 -1
  59. data/qed/01_openhash.rdoc +0 -57
  60. data/qed/02_queryhash.rdoc +0 -21
  61. data/qed/03_castinghash.rdoc +0 -13
  62. data/qed/04_statichash.rdoc +0 -22
  63. data/qed/05_association.rdoc +0 -59
  64. data/qed/06_opencascade.rdoc +0 -58
  65. data/qed/07_fuzzyhash.rdoc +0 -141
  66. data/qed/08_properyhash.rdoc +0 -38
  67. data/qed/09_ostructable.rdoc +0 -56
  68. data/qed/applique/ae.rb +0 -1
  69. data/test/case_basicstruct.rb +0 -192
  70. data/test/case_openhash.rb +0 -22
@@ -1 +0,0 @@
1
- require 'hashery/property_hash'
@@ -1 +0,0 @@
1
- require 'hashery/query_hash'
@@ -1 +0,0 @@
1
- require 'hashery/static_hash'
@@ -1,57 +0,0 @@
1
- = OpenHash
2
-
3
- An OpenHash is a Hash that provides +open+ access to its entries via method
4
- calls. Writers (methods ending in =-marks) assign entries. Methods without
5
- special puncuation will retrieve entries.
6
-
7
- require 'hashery/openhash'
8
-
9
- o = OpenHash.new
10
- o.a = 1
11
- o.b = 2
12
- o.a.assert == 1
13
- o.b.assert == 2
14
-
15
- Writers always use a Symbol for keys in the underlying Hash.
16
-
17
- o.to_h.assert == { :a=>1, :b=>2 }
18
-
19
- All the usual Hash methods are still available in an OpenHash.
20
-
21
- o.map{ |k,v| [k,v] }
22
-
23
- And they are protected from being overridden by writers.
24
-
25
- o.map = 3
26
- o.map{ |k,v| [k,v] }
27
-
28
- Even so, the underlying Hash object does contain the entry even
29
- when it can not be accessed via a reader method.
30
-
31
- o.to_h.assert == {:a=>1, :b=>2, :map=>3 }
32
-
33
- For some usecases it may be necessary to give up access to one or
34
- more Hash methods in favor of access to the hash entries. This can
35
- be done using the #omit! method.
36
-
37
- o.omit!(:map, :merge)
38
- o.map.assert == 3
39
- o.merge = 4
40
- o.merge.assert == 4
41
-
42
- Becuase of nature of a writer, a certain set of Hash methods are always
43
- protected, namely any of those ending in a puctuation mark. In addition,
44
- the implementation protects all shadow methods (e.g. __id__).
45
-
46
- o.__id__ = 4
47
- o.__id__.assert! == 4
48
-
49
- Even though writers alwasy use Symbols as keys, because an OpenHash
50
- is a true Hash object, any object can be used as a key internally.
51
-
52
- o = OpenHash.new
53
- o[nil] = "Nothing"
54
- o.to_h.assert == { nil=>"Nothing" }
55
-
56
- It simply will not be accessible via a reader method.
57
-
@@ -1,21 +0,0 @@
1
- = QueryHash
2
-
3
- A QueryHash is a Hash that provides open access much like
4
- an OpenHash, but it limits readers to query methods (i.e.
5
- method ending in ?-marks).
6
-
7
- require 'hashery/queryhash'
8
-
9
- q = QueryHash.new
10
- q.a = 1
11
- q.b = 2
12
- q.a?.assert == 1
13
- q.b?.assert == 2
14
-
15
- Writers always use Symbols for entry keys.
16
-
17
- q.assert == { :a=>1, :b=>2 }
18
-
19
- A QueryHash is compatible with Ruby's standard Hash in
20
- every other respect.
21
-
@@ -1,13 +0,0 @@
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
- require 'hashery/castinghash'
7
-
8
- c = CastingHash.new{ |x| x.to_s }
9
-
10
- c[:a] = 1
11
-
12
- c.assert == {'a'=>1}
13
-
@@ -1,22 +0,0 @@
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
- require 'hashery/statichash'
8
-
9
- h = StaticHash.new
10
-
11
- h["x"] = 1
12
-
13
- expect ArgumentError do
14
- h["x"] = 2
15
- end
16
-
17
- The same error will be raised when using #update or #merge!.
18
-
19
- expect ArgumentError do
20
- h.update( :x=>2 )
21
- end
22
-
@@ -1,59 +0,0 @@
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
-
@@ -1,58 +0,0 @@
1
- = OpenCascade
2
-
3
- OpenCascade is subclass of OpenObject. It differs in a few
4
- significant ways.
5
-
6
- require 'hashery/opencascade'
7
-
8
- The reason this class is labeled "cascade", is that every internal
9
- Hash is transformed into an OpenCascade dynamically upon access.
10
- This makes it easy to create _cascading_ references.
11
-
12
- h = { :x => { :y => { :z => 1 } } }
13
- c = OpenCascade[h]
14
- assert c.x.y.z == 1
15
-
16
- As soon as you access a node it automatically becomes an OpenCascade.
17
-
18
- c = OpenCascade.new
19
- assert c.r.is_a?(OpenCascade)
20
- assert c.a.b.is_a?(OpenCascade)
21
-
22
- But if you set a node, then that will be it's value.
23
-
24
- c.a.b = 4
25
- assert c.a.b == 4
26
-
27
- To query a node without causing the auto-creation of an OpenCasade
28
- object, use the ?-mark.
29
-
30
- assert c.a.z? == nil
31
-
32
- OpenCascade also transforms Hashes within Arrays.
33
-
34
- h = { :x=>[ {:a=>1}, {:a=>2} ], :y=>1 }
35
- c = OpenCascade[h]
36
- assert c.x.first.a == 1
37
- assert c.x.last.a == 2
38
-
39
- Like OpenObject, OpenCascade allows you to insert entries as array
40
- pairs.
41
-
42
- c = OpenCascade.new
43
- c << [:x,8]
44
- c << [:y,9]
45
-
46
- assert c.x == 8
47
- assert c.y == 9
48
-
49
- Finally, you can call methods ending in a !-mark to access the
50
- underlying hash (Note that these differ in behavior from the
51
- built-in !-methods).
52
-
53
- bk = c.map!{ |k,v| k.to_s.upcase }
54
- bk.sort.assert == ['X', 'Y']
55
-
56
- So you can see that for the most an OpenCascade is just like
57
- OpenObject, but it allows you to conveniently build open sub-layers.
58
-
@@ -1,141 +0,0 @@
1
- = FuzzyHash
2
-
3
- Require the library.
4
-
5
- require 'hashery/fuzzyhash'
6
-
7
- Should accept strings and retrieve based on them.
8
-
9
- l = FuzzyHash.new
10
- l['asd'] = 'qwe'
11
- l['asd'].should == 'qwe'
12
-
13
- Should accept strings, but the second time you set the same string, it should overwrite.
14
-
15
- l = FuzzyHash.new
16
- l['asd'] = 'asd'
17
- l['asd'] = 'qwe'
18
- l['asd'].should == 'qwe'
19
-
20
- Should accept regexs too.
21
-
22
- l = FuzzyHash.new
23
- l[/asd.*/] = 'qwe'
24
- l['asdqweasd'].should == 'qwe'
25
-
26
- Should accept regexs too, but the second time you set the same regex, it should overwrite.
27
-
28
- l = FuzzyHash.new
29
- l[/asd/] = 'asd'
30
- l[/asd/] = 'qwe'
31
- l['asdqweasd'].should == 'qwe'
32
-
33
- Should accept regexs too with the match.
34
-
35
- l = FuzzyHash.new
36
- l[/asd.*/] = 'qwe'
37
- l.match_with_result('asdqweasd').should == ['qwe', 'asdqweasd']
38
-
39
- Should accept regexs that match the whole strong too with the match.
40
-
41
- l = FuzzyHash.new
42
- l[/asd/] = 'qwe'
43
- l.match_with_result('asd').should == ['qwe', 'asd']
44
-
45
- Should prefer string to regex matches.
46
-
47
- l = FuzzyHash.new
48
- l['asd'] = 'qwe2'
49
- l[/asd.*/] = 'qwe'
50
- l['asd'].should == 'qwe2'
51
-
52
- Should allow nil keys.
53
-
54
- l = FuzzyHash.new
55
- l[nil] = 'qwe2'
56
- l['asd'] = 'qwe'
57
- l['asd'].should == 'qwe'
58
- l[nil].should == 'qwe2'
59
-
60
- Should allow boolean keys.
61
-
62
- l = FuzzyHash.new
63
- l[false] = 'false'
64
- l[true] = 'true'
65
- l[/.*/] = 'everything else'
66
- l[true].should == 'true'
67
- l[false].should == 'false'
68
- l['false'].should == 'everything else'
69
-
70
- Should pick between the correct regex.
71
-
72
- hash = FuzzyHash.new
73
- hash[/^\d+$/] = 'number'
74
- hash[/.*/] = 'something'
75
- hash['123asd'].should == 'something'
76
-
77
- Should be able to delete by value for hash.
78
-
79
- l = FuzzyHash.new
80
- l[nil] = 'qwe2'
81
- l['asd'] = 'qwe'
82
- l['asd'].should == 'qwe'
83
- l[nil].should == 'qwe2'
84
- l.delete_value('qwe2')
85
- l[nil].should == nil
86
-
87
- Should be able to delete by value for regex.
88
-
89
- l = FuzzyHash.new
90
- l[/qwe.*/] = 'qwe2'
91
- l['asd'] = 'qwe'
92
- l['asd'].should == 'qwe'
93
- l['qweasd'].should == 'qwe2'
94
- l.delete_value('qwe2')
95
- l['qweasd'].should == nil
96
-
97
- Should iterate through the keys.
98
-
99
- l = FuzzyHash.new
100
- l[/qwe.*/] = 'qwe2'
101
- l['asd'] = 'qwe'
102
- l['zxc'] = 'qwe'
103
- l.keys.size.should == 3
104
-
105
- Should iterate through the values.
106
-
107
- l = FuzzyHash.new
108
- l[/qwe.*/] = 'qwe2'
109
- l['asd'] = 'qwe'
110
- l['zxc'] = 'qwelkj'
111
- (['qwe2','qwe','qwelkj'] & l.values).size.should == 3
112
-
113
- Should clear.
114
-
115
- l = FuzzyHash.new
116
- l[/qwe.*/] = 'qwe2'
117
- l['asd'] = 'qwe'
118
- l['zxc'] = 'qwelkj'
119
- l.clear
120
- l.empty?.should == true
121
-
122
- Should handle equality.
123
-
124
- l_1 = FuzzyHash.new
125
- l_1[/qwe.*/] = 'qwe2'
126
- l_1['asd'] = 'qwelkj'
127
- l_1['zxc'] = 'qwe'
128
- l_2 = FuzzyHash.new
129
- l_2['zxc'] = 'qwe'
130
- l_2['asd'] = 'qwelkj'
131
- l_2[/qwe.*/] = 'qwe2'
132
- l_1.should == l_2
133
-
134
- Should return the value when adding the value.
135
-
136
- h = FuzzyHash.new
137
- (h[/asd/] = '123').should == '123'
138
- (h['qwe'] = '123').should == '123'
139
-
140
- That's It.
141
-
@@ -1,38 +0,0 @@
1
- = PropertyHash
2
-
3
- Require the library.
4
-
5
- require 'hashery/propertyhash'
6
-
7
- The Property hash can be used an object in itself.
8
-
9
- h = PropertyHash.new(:a=>1, :b=>2)
10
- h[:a] #=> 1
11
- h[:a] = 3
12
- h[:a] #=> 3
13
-
14
- Becuase the properties are fixed, if we try to set a key that is not present,
15
- then we will get an error.
16
-
17
- expect ArgumentError do
18
- h[:x] = 5
19
- end
20
-
21
- The PropertyHash can also be used as a superclass.
22
-
23
- class MyPropertyHash < PropertyHash
24
- property :a, :default => 1
25
- property :b, :default => 2
26
- end
27
-
28
- h = MyPropertyHash.new
29
- h[:a] #=> 1
30
- h[:a] = 3
31
- h[:a] #=> 3
32
-
33
- Again, if we try to set key that was not fixed, then we will get an error.
34
-
35
- expect ArgumentError do
36
- h[:x] = 5
37
- end
38
-
@@ -1,56 +0,0 @@
1
- = OpenStructable
2
-
3
- OpensStructable is a mixin module which can provide OpenStruct behavior to
4
- any class or object. OpenStructable allows extention of data objects
5
- with arbitrary attributes.
6
-
7
- require 'hashery/ostructable'
8
-
9
- class Record
10
- include OpenStructable
11
- end
12
-
13
- Now let's create a new record and see if we can assign values to open
14
- properties.
15
-
16
- record = Record.new
17
- record.name = "John Smith"
18
- record.age = 70
19
- record.pension = 300
20
-
21
- We can see that the values were set.
22
-
23
- record.name.assert == "John Smith"
24
- record.age.assert == 70
25
- record.pension.assert == 300
26
-
27
- If we havent' assigned a value to a property it should just return +nil+.
28
-
29
- record.address.assert == nil
30
-
31
- OpenStructable is also smart enough to adjust itself to work with a subclass
32
- of a Hash.
33
-
34
- class HashRecord < Hash
35
- include OpenStructable
36
- end
37
-
38
- We can apply similar settings as above.
39
-
40
- record = HashRecord.new
41
- record.name = "John Doe"
42
- record.age = 40
43
- record.pension = 200
44
-
45
- We can see that the values were set.
46
-
47
- record.name.assert == "John Doe"
48
- record.age.assert == 40
49
- record.pension.assert == 200
50
-
51
- The differnce here is that the data is accessible via the normal Hash
52
- methods too.
53
-
54
- record.assert == {:name=>"John Doe", :age=>40, :pension=>200}
55
-
56
- Notice that entries are converted to Symbols, not Strings.