kissifer-hash-persistent 0.0.0 → 0.0.3

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/spec/spec_helper.rb CHANGED
@@ -1,6 +1,4 @@
1
- require 'rubygems'
2
1
  require 'spec'
3
- require 'ostruct'
4
2
 
5
3
  $LOAD_PATH.unshift(File.dirname(__FILE__))
6
4
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kissifer-hash-persistent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - kissifer
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-23 00:00:00 -07:00
12
+ date: 2009-05-22 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -31,18 +31,12 @@ files:
31
31
  - VERSION
32
32
  - hash-persistent.gemspec
33
33
  - lib/hash-persistent.rb
34
- - lib/hash-persistent/collection.rb
35
- - lib/hash-persistent/counter.rb
36
- - lib/hash-persistent/extended_store.rb
37
- - lib/hash-persistent/resource.rb
38
- - lib/hash-persistent/store.rb
39
- - spec/collection_spec.rb
40
- - spec/counter_spec.rb
41
- - spec/extended_store_spec.rb
42
- - spec/resource_spec.rb
34
+ - lib/hash-persistent/basic.rb
35
+ - lib/hash-persistent/counting.rb
36
+ - spec/basic_spec.rb
37
+ - spec/counting_spec.rb
43
38
  - spec/spec.opts
44
39
  - spec/spec_helper.rb
45
- - spec/store_spec.rb
46
40
  has_rdoc: false
47
41
  homepage: http://github.com/kissifer/hash-persistent
48
42
  post_install_message:
@@ -68,11 +62,8 @@ rubyforge_project:
68
62
  rubygems_version: 1.2.0
69
63
  signing_key:
70
64
  specification_version: 3
71
- summary: Library of base classes to simplify persisting objects and collections to a moneta store
65
+ summary: Library of base classes to simplify persisting objects in a moneta store
72
66
  test_files:
73
- - spec/collection_spec.rb
74
- - spec/counter_spec.rb
75
- - spec/extended_store_spec.rb
76
- - spec/resource_spec.rb
67
+ - spec/basic_spec.rb
68
+ - spec/counting_spec.rb
77
69
  - spec/spec_helper.rb
78
- - spec/store_spec.rb
@@ -1,59 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/resource')
2
-
3
- module HashPersistent
4
- module Collection
5
- include HashPersistent::Resource
6
-
7
- def self.included(base)
8
- base.extend ClassMethods
9
- end
10
-
11
- module ClassMethods
12
- attr_accessor :basis
13
-
14
- def on_watched_store_save_event(store_for_collection, saved_object)
15
- raise "Cannot collect objects without a basis for the collection. Set :basis class attribute" unless @basis
16
- return unless saved_object.respond_to?(:basis) && saved_object.respond_to?(:key)
17
-
18
- collection_resource = store_for_collection.find(saved_object.send(:basis))
19
- unless collection_resource
20
- collection_resource = new
21
- collection_resource.store = store_for_collection
22
- collection_resource.key = saved_object.send(:basis)
23
- end
24
-
25
- collection_resource.collected_keys << saved_object.send(:key)
26
- collection_resource.collected_keys.uniq!
27
- collection_resource.save
28
- end
29
-
30
- def on_watched_store_delete_event(store_for_collection, deleted_object)
31
- raise "Cannot collect objects without a basis for the collection. Set :basis class attribute" unless @basis
32
- return unless deleted_object.respond_to?(:basis) && deleted_object.respond_to?(:key)
33
-
34
- collection_resource = store_for_collection.find(deleted_object.send(:basis))
35
- return unless collection_resource
36
-
37
- collection_resource.collected_keys.delete(deleted_object.send(:key))
38
-
39
- if collection_resource.collected_keys == []
40
- collection_resource.delete
41
- else
42
- collection_resource.save
43
- end
44
- end
45
- end
46
-
47
- def collected_keys
48
- @collected_keys ||= []
49
- end
50
-
51
- def collected_resources
52
- @collected_keys.collect do |key|
53
- resource = store.watching.find(key)
54
- raise "Collected key not found in watched store" unless resource
55
- resource
56
- end
57
- end
58
- end
59
- end
@@ -1,26 +0,0 @@
1
- require 'ostruct'
2
-
3
- module HashPersistent
4
- class Counter
5
- def initialize(store, key)
6
- raise ArgumentError unless store.is_a?(HashPersistent::Store) and key.respond_to?(:to_s) and key.to_s.length != 0
7
- @store = store
8
- @key = key
9
-
10
- unless @store.find(@key)
11
- counter = OpenStruct.new
12
- counter.key = @key
13
- counter.count = 0
14
- @store.save(counter)
15
- end
16
- end
17
-
18
- def next
19
- counter = @store.find(@key)
20
- next_count = counter.count
21
- counter.count += 1
22
- @store.save(counter)
23
- next_count
24
- end
25
- end
26
- end
@@ -1,49 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/store')
2
-
3
- module HashPersistent
4
- class ExtendedStore
5
- attr_reader :store
6
-
7
- def initialize(store)
8
- @store = store
9
- yield self if block_given?
10
- end
11
-
12
- def find(key)
13
- a_singleton = singleton_keys.find do |singleton|
14
- key.match(singleton[0])
15
- end
16
-
17
- if a_singleton
18
- find_or_create(key, a_singleton[1], *a_singleton[2], &a_singleton[3])
19
- else
20
- @store.find(key)
21
- end
22
- end
23
-
24
- def save(object)
25
- @store.save(object)
26
- end
27
-
28
- def delete(object)
29
- @store.delete(object)
30
- end
31
-
32
- def create(key, class_to_create, *args, &block)
33
- @store.create(key, class_to_create, *args, &block)
34
- end
35
-
36
- def find_or_create(key, class_to_create, *args, &block)
37
- @store.find_or_create(key, class_to_create, *args, &block)
38
- end
39
-
40
- def singleton_key(pattern, class_to_create, *args, &block)
41
- "1".match(pattern) # a test to check the duck typing early
42
- singleton_keys << [pattern, class_to_create, args, block]
43
- end
44
-
45
- def singleton_keys
46
- @singleton_keys ||= []
47
- end
48
- end
49
- end
@@ -1,20 +0,0 @@
1
- module HashPersistent
2
- module Resource
3
- attr_accessor :store, :key
4
-
5
- def save
6
- @store.save(self) if @store
7
- end
8
-
9
- def delete
10
- @store.delete(self) if @store
11
- end
12
-
13
- def move(new_store)
14
- delete
15
- @store = new_store
16
- save
17
- end
18
- end
19
- end
20
-
@@ -1,67 +0,0 @@
1
- module HashPersistent
2
- class Store
3
- attr_reader :key_value_store, :key_prefix, :cached_to
4
-
5
- def initialize(key_value_store, key_prefix)
6
- raise ArgumentError unless key_value_store.respond_to?(:has_key?) and key_prefix.respond_to?(:to_s)
7
- @key_value_store = key_value_store
8
- @key_prefix = key_prefix
9
- yield self if block_given?
10
- end
11
-
12
- def cached_to=(cache)
13
- raise ArgumentError unless cache.is_a?(HashPersistent::Store) if cache
14
- @cached_to = cache
15
- end
16
-
17
- def save(object)
18
- store_this = object.dup
19
- store_this.store = nil if store_this.respond_to?(:store)
20
- @key_value_store[@key_prefix + store_this.key] = store_this
21
-
22
- @cached_to.save(object) if @cached_to
23
-
24
- object.store = self if object.respond_to?(:store)
25
- self
26
- end
27
-
28
- def delete(object)
29
- @key_value_store.delete(@key_prefix + object.key)
30
- @cached_to.delete(object) if @cached_to
31
-
32
- object.store = self if object.respond_to?(:store)
33
- self
34
- end
35
-
36
- def find(key)
37
- if @cached_to
38
- found = @cached_to.find(key)
39
- unless found
40
- found = @key_value_store[@key_prefix + key]
41
- @cached_to.save(found) if found
42
- end
43
- else
44
- found = @key_value_store[@key_prefix + key]
45
- end
46
- return nil unless found
47
-
48
- object = found.dup
49
- object.store = self if object.respond_to?(:store)
50
-
51
- object
52
- end
53
-
54
- def create(key, class_to_create, *args, &block)
55
- object = class_to_create.new(*args, &block)
56
- object.key = key
57
- object.store = self if object.respond_to?(:store)
58
- object
59
- end
60
-
61
- def find_or_create(key, class_to_create, *args, &block)
62
- #TODO: Lock?
63
- save(create(key, class_to_create, *args, &block)) unless find(key)
64
- find(key)
65
- end
66
- end
67
- end
@@ -1,269 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
- require 'ostruct'
3
-
4
- __END__
5
-
6
- class CollectionFoo
7
- include HashPersistent::Collection
8
- end
9
-
10
- class CollectionDoNotSetABasis
11
- include HashPersistent::Collection
12
- end
13
-
14
- describe "A class that includes HashPersistent::Collection" do
15
- it "should include the HashPersistent::Resource module" do
16
- CollectionFoo.included_modules.should include(HashPersistent::Resource)
17
- end
18
-
19
- it "should acquire on_watched_store_save_event() and on_watched_store_delete_event() methods" do
20
- CollectionFoo.respond_to?(:on_watched_store_save_event).should be_true
21
- CollectionFoo.respond_to?(:on_watched_store_delete_event).should be_true
22
- end
23
-
24
- it "should acquire a basis attribute" do
25
- CollectionFoo.basis = "foo"
26
- CollectionFoo.basis.should == "foo"
27
- end
28
-
29
- context "(when not given a basis)" do
30
- it "should complain when given a save event" do
31
- lambda{CollectionDoNotSetABasis.on_watched_store_save_event("store", "saved_object")}.should raise_error
32
- end
33
-
34
- it "should complain when given a delete event" do
35
- lambda{CollectionDoNotSetABasis.on_watched_store_delete_event("store", "deleted_object")}.should raise_error
36
- end
37
- end
38
-
39
- context "(when a save event happens)" do
40
- before(:each) do
41
- CollectionFoo.basis = :basis
42
- @store = HashPersistent::Store.new({}, "")
43
- end
44
-
45
- it "should create a resource for the basis if one does not exist" do
46
- object = OpenStruct.new
47
- object.key = "key"
48
- object.basis = "basis"
49
-
50
- CollectionFoo.on_watched_store_save_event(@store, object)
51
- @store.find("basis").should_not be_nil
52
- end
53
-
54
- it "should collect the saved keys for a basis, in the resource for that basis" do
55
- object = OpenStruct.new
56
- object.basis = "basis"
57
-
58
- object.key = "key_1"
59
- CollectionFoo.on_watched_store_save_event(@store, object)
60
-
61
- object.key = "key_2"
62
- CollectionFoo.on_watched_store_save_event(@store, object)
63
-
64
- collection_resource = @store.find("basis")
65
- collection_resource.collected_keys.should include("key_1")
66
- collection_resource.collected_keys.should include("key_2")
67
- end
68
-
69
- it "should not duplicate keys in the resource for the basis" do
70
- object = OpenStruct.new
71
- object.basis = "basis"
72
-
73
- object.key = "key_1"
74
- CollectionFoo.on_watched_store_save_event(@store, object)
75
- CollectionFoo.on_watched_store_save_event(@store, object)
76
-
77
- object.key = "key_2"
78
- CollectionFoo.on_watched_store_save_event(@store, object)
79
-
80
- collection_resource = @store.find("basis")
81
- collection_resource.collected_keys.size.should == 2
82
- end
83
-
84
- it "should not cross-contaminate keys between bases" do
85
- object = OpenStruct.new
86
-
87
- object.basis = "basis_1"
88
- object.key = "key_1A"
89
- CollectionFoo.on_watched_store_save_event(@store, object)
90
- object.key = "key_1B"
91
- CollectionFoo.on_watched_store_save_event(@store, object)
92
-
93
- object.basis = "basis_2"
94
- object.key = "key_2"
95
- CollectionFoo.on_watched_store_save_event(@store, object)
96
-
97
- collection_resource_1 = @store.find("basis_1")
98
- collection_resource_2 = @store.find("basis_2")
99
-
100
- collection_resource_1.collected_keys.should include("key_1A")
101
- collection_resource_1.collected_keys.should include("key_1B")
102
- collection_resource_1.collected_keys.should_not include("key_2")
103
-
104
- collection_resource_2.collected_keys.should_not include("key_1A")
105
- collection_resource_2.collected_keys.should_not include("key_1B")
106
- collection_resource_2.collected_keys.should include("key_2")
107
- end
108
- end
109
-
110
- context "(when a delete event happens)" do
111
- before(:each) do
112
- CollectionFoo.basis = :basis
113
- @store = HashPersistent::Store.new({}, "")
114
- end
115
-
116
- it "should not complain when asked to remove a key from an unknown basis" do
117
- object = OpenStruct.new
118
-
119
- object.basis = "basis"
120
- object.key = "key"
121
- lambda{CollectionFoo.on_watched_store_delete_event(@store, object)}.should_not raise_error
122
- end
123
-
124
- it "should delete the key from the resource for a basis" do
125
- object = OpenStruct.new
126
-
127
- object.basis = "basis"
128
- object.key = "key_1"
129
- CollectionFoo.on_watched_store_save_event(@store, object) # save
130
- object.key = "key_2"
131
- CollectionFoo.on_watched_store_save_event(@store, object) # save
132
-
133
- object.key = "key_1"
134
- CollectionFoo.on_watched_store_delete_event(@store, object) # delete
135
-
136
- collection_resource = @store.find("basis")
137
-
138
- collection_resource.collected_keys.should include("key_2")
139
- collection_resource.collected_keys.should_not include("key_1")
140
- end
141
-
142
- it "should not complain when asked to remove a non-existent key from the basis" do
143
- object = OpenStruct.new
144
-
145
- object.basis = "basis"
146
- object.key = "key_1"
147
- CollectionFoo.on_watched_store_save_event(@store, object)
148
-
149
- object.key = "key_2"
150
- lambda{CollectionFoo.on_watched_store_delete_event(@store, object)}.should_not raise_error
151
- end
152
-
153
- it "should remove the resource for a basis when the last key is removed" do
154
- object = OpenStruct.new
155
-
156
- object.basis = "basis"
157
- object.key = "key"
158
- CollectionFoo.on_watched_store_save_event(@store, object)
159
- CollectionFoo.on_watched_store_delete_event(@store, object)
160
-
161
- @store.find("basis").should be_nil
162
- end
163
-
164
- it "should not complain when asked to remove a key from a deleted basis" do
165
- object = OpenStruct.new
166
-
167
- object.basis = "basis"
168
- object.key = "key"
169
- CollectionFoo.on_watched_store_save_event(@store, object)
170
- CollectionFoo.on_watched_store_delete_event(@store, object)
171
- lambda{CollectionFoo.on_watched_store_delete_event(@store, object)}.should_not raise_error
172
- end
173
- end
174
-
175
- it "should do nothing when told about save or delete events for objects with no key attribute" do
176
- store = HashPersistent::Store.new({}, "")
177
- object = OpenStruct.new
178
- object.basis = "fred"
179
-
180
- CollectionFoo.on_watched_store_save_event(store, object)
181
- store.key_value_store.should == {}
182
- CollectionFoo.on_watched_store_delete_event(store, object)
183
- store.key_value_store.should == {}
184
- end
185
-
186
- it "should do nothing when told about save or delete events for objects with no basis attribute" do
187
- store = HashPersistent::Store.new({}, "")
188
- object = OpenStruct.new
189
- object.key = "fred"
190
-
191
- CollectionFoo.on_watched_store_save_event(store, object)
192
- store.key_value_store.should == {}
193
- CollectionFoo.on_watched_store_delete_event(store, object)
194
- store.key_value_store.should == {}
195
- end
196
-
197
- context "(dereferencing collected keys)" do
198
- it "should provide a convenient means to retrieve/dereference collected resources" do
199
- watched_store = HashPersistent::Store.new({}, "")
200
- watching_store = HashPersistent::Store.new({}, "")
201
- watching_store.watch(watched_store)
202
- watching_store.managed_class = CollectionFoo
203
- CollectionFoo.basis = :basis
204
-
205
- object = OpenStruct.new
206
-
207
- object.basis = "fred"
208
- object.key = "1"
209
- watched_store.save(object)
210
-
211
- object.basis = "fred"
212
- object.key = "2"
213
- watched_store.save(object)
214
-
215
- object.basis = "barney"
216
- object.key = "3"
217
- watched_store.save(object)
218
-
219
- fred = watching_store.find("fred")
220
- fred.collected_resources.should include(watched_store.find("1"))
221
- fred.collected_resources.should include(watched_store.find("2"))
222
- end
223
-
224
- it "should complain if asked to dereference a resource that does not exist in the watched store" do
225
- watched_store = HashPersistent::Store.new({}, "")
226
- watching_store = HashPersistent::Store.new({}, "")
227
- watching_store.managed_class = CollectionFoo
228
- watching_store.watch(watched_store)
229
- CollectionFoo.basis = :basis
230
-
231
- object = OpenStruct.new
232
- object.basis = "fred"
233
- object.key = "1"
234
- watched_store.save(object)
235
-
236
- object.basis = "fred"
237
- object.key = "2"
238
- watched_store.save(object)
239
-
240
- watched_store.watched_by = nil
241
- watched_store.delete(object)
242
- watched_store.watched_by = watching_store
243
-
244
- fred = watching_store.find("fred")
245
- lambda{fred.collected_resources}.should raise_error
246
- end
247
-
248
- it "should complain if asked to dereference a resource but does not know what store it's watching" do
249
- watched_store = HashPersistent::Store.new({}, "")
250
- watching_store = HashPersistent::Store.new({}, "")
251
- watching_store.managed_class = CollectionFoo
252
- watched_store.watched_by = watching_store # Note, only on-way relationship here
253
- CollectionFoo.basis = :basis
254
-
255
- object = OpenStruct.new
256
- object.basis = "fred"
257
- object.key = "1"
258
- watched_store.save(object)
259
-
260
- object.basis = "fred"
261
- object.key = "2"
262
- watched_store.save(object)
263
-
264
- fred = watching_store.find("fred")
265
- lambda{fred.collected_resources}.should raise_error
266
- end
267
- end
268
- end
269
-