hashery 1.5.0 → 2.0.0

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 (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.