kissifer-hash-persistent 0.2.2 → 0.3.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.
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "hash-persistent"
8
- gem.summary = %Q{Library of base classes to simplify persisting objects in a moneta store}
8
+ gem.summary = %Q{Library of base classes to simplify persisting objects and collections to a moneta store}
9
9
  gem.email = "tierneydrchris@gmail.com"
10
10
  gem.homepage = "http://github.com/kissifer/hash-persistent"
11
11
  gem.authors = ["kissifer"]
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.3.1
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{hash-persistent}
5
- s.version = "0.2.2"
5
+ s.version = "0.3.1"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["kissifer"]
9
- s.date = %q{2009-06-02}
9
+ s.date = %q{2009-06-04}
10
10
  s.email = %q{tierneydrchris@gmail.com}
11
11
  s.extra_rdoc_files = [
12
12
  "LICENSE",
@@ -33,8 +33,8 @@ Gem::Specification.new do |s|
33
33
  s.homepage = %q{http://github.com/kissifer/hash-persistent}
34
34
  s.rdoc_options = ["--charset=UTF-8"]
35
35
  s.require_paths = ["lib"]
36
- s.rubygems_version = %q{1.3.3}
37
- s.summary = %q{Library of base classes to simplify persisting objects in a moneta store}
36
+ s.rubygems_version = %q{1.3.4}
37
+ s.summary = %q{Library of base classes to simplify persisting objects and collections to a moneta store}
38
38
  s.test_files = [
39
39
  "spec/collection_spec.rb",
40
40
  "spec/counter_spec.rb",
@@ -2,18 +2,21 @@ module HashPersistent
2
2
  module Collection
3
3
 
4
4
  def self.included(base)
5
- base.extend ClassMethods
5
+ base.extend ClassMethods_Initial
6
6
  base.module_eval do
7
7
  include HashPersistent::Resource
8
8
  end
9
9
  end
10
10
 
11
- module ClassMethods
12
- attr_reader :resource_class
13
-
11
+ module ClassMethods_Initial
14
12
  def attach(resource_class, collection_basis)
15
- raise ArgumentError unless resource_class.included_modules.include?(HashPersistent::Resource)
16
- raise ArgumentError unless resource_class.instance_methods.include?(collection_basis.to_s)
13
+ raise "You must create a persistent subclass before attaching this collection class. Use HashPersistent::persist_to()" unless included_modules.include?(HashPersistent::Resource::InstanceMethods)
14
+ raise "You can attach this collection class only to a class that has been created with HashPersistent::Resource.persist_to()" unless resource_class.included_modules.include?(HashPersistent::Resource::InstanceMethods)
15
+ raise "Did not find the specified basis attribute (#{collection_basis}) in the given resource class" unless resource_class.instance_methods.include?(collection_basis.to_s)
16
+
17
+ extend ClassMethods
18
+ include InstanceMethods
19
+
17
20
  @collection_basis = collection_basis
18
21
  @resource_class = resource_class
19
22
  resource_class.on_save do |resource|
@@ -24,6 +27,10 @@ module HashPersistent
24
27
  collected_resource_deleted(resource)
25
28
  end
26
29
  end
30
+ end
31
+
32
+ module ClassMethods
33
+ attr_reader :resource_class
27
34
 
28
35
  def collected_resource_saved(resource)
29
36
  collection = find(resource.send(@collection_basis))
@@ -48,11 +55,13 @@ module HashPersistent
48
55
  end
49
56
  end
50
57
 
51
- attr_accessor :collected_keys
58
+ module InstanceMethods
59
+ attr_accessor :collected_keys
52
60
 
53
- def collected_resources
54
- collected_keys.collect do |key|
55
- self.class.resource_class.send(:find, key)
61
+ def collected_resources
62
+ collected_keys.collect do |key|
63
+ self.class.resource_class.send(:find, key)
64
+ end
56
65
  end
57
66
  end
58
67
  end
@@ -1,24 +1,29 @@
1
1
  module HashPersistent
2
2
  module Resource
3
3
  def self.included(base)
4
- base.extend ClassMethods
5
- base.module_eval do
6
- @store = {}
7
- @prefix = ""
8
- end
4
+ base.extend ClassMethods_Initial
9
5
  end
10
-
11
- module ClassMethods
6
+
7
+ module ClassMethods_Initial
12
8
  def persist_to(store, prefix)
13
9
  raise ArgumentError unless store.respond_to?(:has_key?) and prefix.respond_to?(:to_s)
14
- @store = store
15
- @prefix = prefix
10
+ Class.new(self) do
11
+ extend ClassMethods
12
+ include InstanceMethods
13
+
14
+ @store = store
15
+ @prefix = prefix
16
+ end
16
17
  end
18
+ end
17
19
 
20
+ module ClassMethods
21
+ attr_reader :store, :prefix
22
+
18
23
  def find(key)
19
24
  @store[@prefix + key]
20
25
  end
21
-
26
+
22
27
  def on_save(&block)
23
28
  if block
24
29
  @on_save = block
@@ -33,30 +38,30 @@ module HashPersistent
33
38
  else
34
39
  @on_delete
35
40
  end
36
- end
37
-
38
- attr_reader :store, :prefix
41
+ end
39
42
  end
43
+
44
+ module InstanceMethods
45
+ attr_accessor :key
40
46
 
41
- attr_accessor :key
42
-
43
- def prefix_key
44
- self.class.prefix + key
45
- end
47
+ def prefix_key
48
+ self.class.prefix + key
49
+ end
46
50
 
47
- def save
48
- raise RuntimeError unless key
49
- self.class.store[prefix_key] = self
50
- self.class.on_save.call(self) if self.class.on_save
51
- end
51
+ def save
52
+ raise RuntimeError unless key
53
+ self.class.store[prefix_key] = self
54
+ self.class.on_save.call(self) if self.class.on_save
55
+ end
52
56
 
53
- def delete
54
- raise RuntimeError unless key
55
- return unless self.class.store.has_key?(prefix_key)
56
- # TODO concurrency here, the store's delete call should cope, but we don't want the callback if something else got in first?
57
- # Alternative: ensure that callback handles this case, which is true of HashPersistent::Collection
58
- self.class.store.delete(prefix_key)
59
- self.class.on_delete.call(self) if self.class.on_delete
57
+ def delete
58
+ raise RuntimeError unless key
59
+ return unless self.class.store.has_key?(prefix_key)
60
+ # TODO concurrency here, the store's delete call should cope, but we don't want the callback if something else got in first?
61
+ # Alternative: ensure that callback handles this case, which is true of HashPersistent::Collection
62
+ self.class.store.delete(prefix_key)
63
+ self.class.on_delete.call(self) if self.class.on_delete
64
+ end
60
65
  end
61
66
  end
62
67
  end
@@ -13,130 +13,154 @@ class NotAResource
13
13
  end
14
14
 
15
15
  describe "A class that includes HashPersistent::Collection" do
16
- it "should include the HashPersistent::Resource module" do
17
- CollectionFoo.included_modules.should include (HashPersistent::Resource)
18
- end
16
+ context "(before made persistent)" do
17
+ it "should include the HashPersistent::Resource module" do
18
+ CollectionFoo.included_modules.should include (HashPersistent::Resource)
19
+ end
19
20
 
20
- it "should allow itself to be attached to another HashPersistent::Resource, specifying an attribute/method for the collection basis" do
21
- lambda{CollectionFoo.attach(CollectedResource, :basis)}.should_not raise_error
21
+ it "should not allow itself to be attached to a persistent HashPersistent::Resource until it has been made persistent" do
22
+ lambda{CollectionFoo.attach(CollectedResource.persist_to({}, ""), :basis)}.should raise_error
23
+ end
22
24
  end
23
25
 
24
- it "should not attach to the wrong class type" do
25
- lambda{CollectionFoo.attach(NotAResource, :basis)}.should raise_error
26
- lambda{CollectionFoo.attach(1, :basis)}.should raise_error
27
- end
26
+ context "(once made persistent via the persist_to method)" do
27
+ it "should not add methods, except attach(), before attached to another persisted resource" do
28
+ # Grey-box here...
29
+ CollectionFoo.persist_to({}, "").respond_to?(:resource_class).should be_false
30
+ CollectionFoo.persist_to({}, "").respond_to?(:collected_resource_saved).should be_false
31
+ CollectionFoo.persist_to({}, "").respond_to?(:collected_resource_deleted).should be_false
32
+
33
+ CollectionFoo.persist_to({}, "").new.respond_to?(:collected_keys).should be_false
34
+ CollectionFoo.persist_to({}, "").new.respond_to?(:collected_resources).should be_false
35
+ CollectionFoo.persist_to({}, "").new.respond_to?(:collected_resources).should be_false
36
+ end
37
+
38
+ it "should not attach to the wrong class type" do
39
+ lambda{CollectionFoo.attach(NotAResource, :basis)}.should raise_error
40
+ lambda{CollectionFoo.attach(1, :basis)}.should raise_error
41
+ end
42
+
43
+ it "should not allow itself to be attached to an un-persisted HashPersistent::Resource" do
44
+ lambda{CollectionFoo.attach(CollectedResource, :basis)}.should raise_error
45
+ end
46
+
28
47
 
29
- it "should verify a valid collection basis" do
30
- lambda{CollectionFoo.attach(CollectedResource)}.should raise_error
31
- lambda{CollectionFoo.attach(CollectedResource, :not_a_valid_attr)}.should raise_error
48
+ it "should allow itself to be attached to a persisted HashPersistent::Resource, specifying an attribute/method for the collection basis" do
49
+ lambda{CollectionFoo.persist_to({}, "").attach(CollectedResource.persist_to({}, ""), :basis)}.should_not raise_error
50
+ end
51
+
52
+ it "should verify a valid collection basis" do
53
+ lambda{CollectionFoo.persist_to({}, "").attach(CollectedResource.persist_to({}, ""))}.should raise_error
54
+ lambda{CollectionFoo.persist_to({}, "").attach(CollectedResource.persist_to({}, ""), :not_a_valid_attr)}.should raise_error
55
+ end
32
56
  end
33
57
 
34
58
  context "(when attached resources are saved/deleted)" do
35
59
  it "should create a collection for a new basis" do
36
- CollectionFoo.persist_to({}, "")
37
- CollectedResource.persist_to({}, "")
60
+ collection_class = CollectionFoo.persist_to({}, "")
61
+ resource_class = CollectedResource.persist_to({}, "")
38
62
 
39
- CollectionFoo.attach(CollectedResource, :basis)
40
- CollectionFoo.find("the_basis").should == nil
63
+ collection_class.attach(resource_class, :basis)
64
+ collection_class.find("the_basis").should == nil
41
65
 
42
- resource = CollectedResource.new
66
+ resource = resource_class.new
43
67
  resource.basis = "the_basis"
44
68
  resource.key = "fred"
45
69
  resource.save
46
70
 
47
- CollectionFoo.find("the_basis").should_not == nil
71
+ collection_class.find("the_basis").should_not == nil
48
72
  end
49
73
 
50
74
  it "should report keys saved/added to the collection" do
51
- CollectionFoo.persist_to({}, "")
52
- CollectedResource.persist_to({}, "")
75
+ collection_class = CollectionFoo.persist_to({}, "")
76
+ resource_class = CollectedResource.persist_to({}, "")
53
77
 
54
- CollectionFoo.attach(CollectedResource, :basis)
78
+ collection_class.attach(resource_class, :basis)
55
79
 
56
- resource = CollectedResource.new
80
+ resource = resource_class.new
57
81
  resource.basis = "the_basis"
58
82
  resource.key = "fred"
59
83
  resource.save
60
84
 
61
- CollectionFoo.find("the_basis").collected_keys.should == ["fred"]
85
+ collection_class.find("the_basis").collected_keys.should == ["fred"]
62
86
 
63
- resource = CollectedResource.new
87
+ resource = resource_class.new
64
88
  resource.basis = "the_basis"
65
89
  resource.key = "barney"
66
90
  resource.save
67
91
 
68
- CollectionFoo.find("the_basis").collected_keys.should == ["fred", "barney"]
92
+ collection_class.find("the_basis").collected_keys.should == ["fred", "barney"]
69
93
  end
70
94
 
71
95
  it "should not duplicate keys when a resource is saved multiple times" do
72
- CollectionFoo.persist_to({}, "")
73
- CollectedResource.persist_to({}, "")
96
+ collection_class = CollectionFoo.persist_to({}, "")
97
+ resource_class = CollectedResource.persist_to({}, "")
74
98
 
75
- CollectionFoo.attach(CollectedResource, :basis)
99
+ collection_class.attach(resource_class, :basis)
76
100
 
77
- resource = CollectedResource.new
101
+ resource = resource_class.new
78
102
  resource.basis = "the_basis"
79
103
  resource.key = "fred"
80
104
  resource.save
81
105
  resource.save
82
106
 
83
- CollectionFoo.find("the_basis").collected_keys.should == ["fred"]
107
+ collection_class.find("the_basis").collected_keys.should == ["fred"]
84
108
  end
85
109
 
86
110
  it "should not report keys with the wrong basis" do
87
- CollectionFoo.persist_to({}, "")
88
- CollectedResource.persist_to({}, "")
111
+ collection_class = CollectionFoo.persist_to({}, "")
112
+ resource_class = CollectedResource.persist_to({}, "")
89
113
 
90
- CollectionFoo.attach(CollectedResource, :basis)
114
+ collection_class.attach(resource_class, :basis)
91
115
 
92
- resource = CollectedResource.new
116
+ resource = resource_class.new
93
117
  resource.basis = "one_basis"
94
118
  resource.key = "fred"
95
119
  resource.save
96
120
 
97
- CollectionFoo.find("another_basis").should == nil
121
+ collection_class.find("another_basis").should == nil
98
122
 
99
- resource = CollectedResource.new
123
+ resource = resource_class.new
100
124
  resource.basis = "another_basis"
101
125
  resource.key = "barney"
102
126
  resource.save
103
127
 
104
- CollectionFoo.find("one_basis").collected_keys.should == ["fred"]
105
- CollectionFoo.find("another_basis").collected_keys.should == ["barney"]
128
+ collection_class.find("one_basis").collected_keys.should == ["fred"]
129
+ collection_class.find("another_basis").collected_keys.should == ["barney"]
106
130
  end
107
131
 
108
132
  it "should remove the key when a resource is deleted" do
109
- CollectionFoo.persist_to({}, "")
110
- CollectedResource.persist_to({}, "")
133
+ collection_class = CollectionFoo.persist_to({}, "")
134
+ resource_class = CollectedResource.persist_to({}, "")
111
135
 
112
- CollectionFoo.attach(CollectedResource, :basis)
136
+ collection_class.attach(resource_class, :basis)
113
137
 
114
- resource = CollectedResource.new
138
+ resource = resource_class.new
115
139
  resource.basis = "the_basis"
116
140
  resource.key = "fred"
117
141
  resource.save
118
142
 
119
- resource = CollectedResource.new
143
+ resource = resource_class.new
120
144
  resource.basis = "the_basis"
121
145
  resource.key = "barney"
122
146
  resource.save
123
147
  resource.delete
124
148
 
125
- CollectionFoo.find("the_basis").collected_keys.should == ["fred"]
149
+ collection_class.find("the_basis").collected_keys.should == ["fred"]
126
150
  end
127
151
 
128
152
  it "should not complain when a not-present key is removed (either not added, or deleted twice)" do
129
- CollectionFoo.persist_to({}, "")
130
- CollectedResource.persist_to({}, "")
153
+ collection_class = CollectionFoo.persist_to({}, "")
154
+ resource_class = CollectedResource.persist_to({}, "")
131
155
 
132
- CollectionFoo.attach(CollectedResource, :basis)
156
+ collection_class.attach(resource_class, :basis)
133
157
 
134
- resource = CollectedResource.new
158
+ resource = resource_class.new
135
159
  resource.basis = "the_basis"
136
160
  resource.key = "fred"
137
161
  resource.save
138
162
 
139
- resource = CollectedResource.new
163
+ resource = resource_class.new
140
164
  resource.basis = "the_basis"
141
165
  resource.key = "barney"
142
166
 
@@ -146,16 +170,16 @@ describe "A class that includes HashPersistent::Collection" do
146
170
  resource.delete
147
171
  lambda{resource.delete}.should_not raise_error
148
172
 
149
- CollectionFoo.find("the_basis").collected_keys.should == ["fred"]
173
+ collection_class.find("the_basis").collected_keys.should == ["fred"]
150
174
  end
151
175
 
152
176
  it "should not complain when a resource with an unknown basis is removed" do
153
- CollectionFoo.persist_to({}, "")
154
- CollectedResource.persist_to({}, "")
177
+ collection_class = CollectionFoo.persist_to({}, "")
178
+ resource_class = CollectedResource.persist_to({}, "")
155
179
 
156
- CollectionFoo.attach(CollectedResource, :basis)
180
+ collection_class.attach(resource_class, :basis)
157
181
 
158
- resource = CollectedResource.new
182
+ resource = resource_class.new
159
183
  resource.basis = "the_basis"
160
184
  resource.key = "fred"
161
185
 
@@ -163,46 +187,46 @@ describe "A class that includes HashPersistent::Collection" do
163
187
  end
164
188
 
165
189
  it "should remove the collection when its final key is removed" do
166
- CollectionFoo.persist_to({}, "")
167
- CollectedResource.persist_to({}, "")
190
+ collection_class = CollectionFoo.persist_to({}, "")
191
+ resource_class = CollectedResource.persist_to({}, "")
168
192
 
169
- CollectionFoo.attach(CollectedResource, :basis)
193
+ collection_class.attach(resource_class, :basis)
170
194
 
171
- resource = CollectedResource.new
195
+ resource = resource_class.new
172
196
  resource.basis = "the_basis"
173
197
  resource.key = "fred"
174
198
  resource.save
175
199
 
176
- resource = CollectedResource.new
200
+ resource = resource_class.new
177
201
  resource.basis = "the_basis"
178
202
  resource.key = "barney"
179
203
  resource.save
180
204
 
181
- CollectedResource.find("fred").delete
182
- CollectedResource.find("barney").delete
205
+ resource_class.find("fred").delete
206
+ resource_class.find("barney").delete
183
207
 
184
- CollectionFoo.find("the_basis").should == nil
208
+ collection_class.find("the_basis").should == nil
185
209
  end
186
210
 
187
211
  it "should be helpful and derefence its keys when asked" do
188
- CollectionFoo.persist_to({}, "")
189
- CollectedResource.persist_to({}, "")
212
+ collection_class = CollectionFoo.persist_to({}, "")
213
+ resource_class = CollectedResource.persist_to({}, "")
190
214
 
191
- CollectionFoo.attach(CollectedResource, :basis)
215
+ collection_class.attach(resource_class, :basis)
192
216
 
193
- resource_1 = CollectedResource.new
217
+ resource_1 = resource_class.new
194
218
  resource_1.basis = "the_basis"
195
219
  resource_1.key = "fred"
196
220
  resource_1.save
197
221
 
198
- CollectionFoo.find("the_basis").collected_resources.should == [resource_1]
222
+ collection_class.find("the_basis").collected_resources.should == [resource_1]
199
223
 
200
- resource_2 = CollectedResource.new
224
+ resource_2 = resource_class.new
201
225
  resource_2.basis = "the_basis"
202
226
  resource_2.key = "barney"
203
227
  resource_2.save
204
228
 
205
- CollectionFoo.find("the_basis").collected_resources.should == [resource_1, resource_2]
229
+ collection_class.find("the_basis").collected_resources.should == [resource_1, resource_2]
206
230
 
207
231
  end
208
232
  end
@@ -25,7 +25,20 @@ class ResourceFooOnlyUsedOnce
25
25
  end
26
26
 
27
27
  describe "A class that includes HashPersistent::Resource" do
28
- context "(class methods)" do
28
+ context "(not initially useful)" do
29
+ it "not gain much from the module" do
30
+ # Grey-box here...
31
+ lambda{ResourceFoo.store}.should raise_error
32
+ lambda{ResourceFoo.prefix}.should raise_error
33
+ lambda{ResourceFoo.on_save}.should raise_error
34
+ lambda{ResourceFoo.on_delete}.should raise_error
35
+ lambda{ResourceFoo.find}.should raise_error
36
+
37
+ ResourceFoo.new.respond_to?(:key=).should be_false
38
+ ResourceFoo.new.respond_to?(:save).should be_false
39
+ ResourceFoo.new.respond_to?(:delete).should be_false
40
+ end
41
+
29
42
  it "should acquire a persist_to class method" do
30
43
  ResourceFoo.respond_to?(:persist_to).should be_true
31
44
  end
@@ -43,76 +56,127 @@ describe "A class that includes HashPersistent::Resource" do
43
56
  it "should reject a non-string-like prefix" do
44
57
  lambda {ResourceFoo.persist_to({}, Dummy_NoStringRep.new)}.should raise_error(ArgumentError)
45
58
  end
46
- end
47
-
59
+
60
+ it "should return a sub-class in response to persist_to" do
61
+ resource_class = ResourceFoo.persist_to({}, "")
62
+ resource_class.should_not == ResourceFoo
63
+ resource_class.superclass.should == ResourceFoo
64
+ end
65
+
66
+ it "should return a different sub-class each time" do
67
+ resource_class_1 = ResourceFoo.persist_to({}, "")
68
+ resource_class_2 = ResourceFoo.persist_to({}, "")
69
+ resource_class_1.should_not == resource_class_2
70
+ end
71
+
72
+ it "should return a sub-class that references the correct store and prefix" do
73
+ store = Hash.new
74
+ store["foo"] = "bar"
75
+ prefix = "baz"
76
+ resource_class = ResourceFoo.persist_to(store, prefix)
77
+ resource_class.store.should == store
78
+ resource_class.prefix.should == prefix
79
+ end
80
+
81
+ it "should return not cross-contaminate the store and prefix of subclasses" do
82
+ store_1 = Hash.new
83
+ store_1["foo"] = "bar"
84
+ prefix_1 = "baz"
85
+ resource_class_1 = ResourceFoo.persist_to(store_1, prefix_1)
86
+ resource_class_2 = ResourceFoo.persist_to(store_1, prefix_1)
87
+
88
+ store_3 = Hash.new
89
+ store_3["fred"] = "barney"
90
+ prefix_3 = "wilma"
91
+ resource_class_3 = ResourceFoo.persist_to(store_3, prefix_3)
92
+
93
+ resource_class_1.store.should == resource_class_2.store
94
+ resource_class_1.prefix.should == resource_class_2.prefix
95
+
96
+ resource_class_1.store.should_not == resource_class_3.store
97
+ resource_class_1.prefix.should_not == resource_class_3.prefix
98
+
99
+ resource_class_1.store.should == store_1
100
+ resource_class_2.store.should == store_1
101
+ resource_class_3.store.should == store_3
102
+
103
+ resource_class_1.prefix.should == prefix_1
104
+ resource_class_2.prefix.should == prefix_1
105
+ resource_class_3.prefix.should == prefix_3
106
+ end
107
+ end
108
+
48
109
  context "(an instance that has not been saved)" do
110
+ before(:each) do
111
+ @resource_class = ResourceFoo.persist_to({}, "")
112
+ end
113
+
49
114
  it "should maintain a key attribute" do
50
- ResourceFoo.new.respond_to?(:key).should be_true
51
- ResourceFoo.new.respond_to?(:key=).should be_true
115
+ @resource_class.new.respond_to?(:key).should be_true
116
+ @resource_class.new.respond_to?(:key=).should be_true
52
117
  end
53
118
 
54
119
  it "should respond to a save method" do
55
- ResourceFoo.new.respond_to?(:save).should be_true
120
+ @resource_class.new.respond_to?(:save).should be_true
56
121
  end
57
122
 
58
123
  it "should respond to a delete method" do
59
- ResourceFoo.new.respond_to?(:delete).should be_true
124
+ @resource_class.new.respond_to?(:delete).should be_true
60
125
  end
61
126
 
62
127
  it "should not save unless the key has been explictly set" do
63
- lambda{ResourceFoo.new.save}.should raise_error
128
+ lambda{@resource_class.new.save}.should raise_error
64
129
  end
65
130
 
66
131
  it "should not delete unless the key has been explictly set" do
67
- lambda{ResourceFoo.new.delete}.should raise_error
132
+ lambda{@resource_class.new.delete}.should raise_error
68
133
  end
69
134
 
70
135
  it "should not complain when deleted, even after a key is set" do
71
- ResourceFoo.persist_to(Hash.new, "")
72
- resource = ResourceFoo.new
136
+ resource = @resource_class.new
73
137
  resource.key = "fred"
74
138
  lambda{resource.delete}.should_not raise_error
75
139
  end
76
140
 
77
141
  it "should not be findable via its key" do
78
- ResourceFoo.persist_to(Hash.new, "")
79
- resource = ResourceFoo.new
142
+ resource = @resource_class.new
80
143
  resource.key = "fred"
81
- ResourceFoo.find("fred").should == nil
82
- ResourceFoo.find("barney").should == nil
144
+ @resource_class.find("fred").should == nil
145
+ @resource_class.find("barney").should == nil
83
146
  end
84
147
  end
85
148
 
86
149
  context "(an instance that has been saved)" do
150
+ before(:each) do
151
+ @resource_class = ResourceFoo.persist_to({}, "")
152
+ @resource_class_with_state = ResourceFooWithState.persist_to({}, "")
153
+ end
154
+
87
155
  it "should be findable via its key" do
88
- ResourceFoo.persist_to(Hash.new, "")
89
- resource = ResourceFoo.new
156
+ resource = @resource_class.new
90
157
  resource.key = "fred"
91
158
  resource.save
92
- ResourceFoo.find("fred").should_not be_nil
159
+ @resource_class.find("fred").should_not be_nil
93
160
  end
94
161
 
95
162
  it "should correctly recover all of its state" do
96
- ResourceFooWithState.persist_to(Hash.new, "")
97
- resource = ResourceFooWithState.new
163
+ resource = @resource_class_with_state.new
98
164
  resource.key = "fred"
99
165
  resource.dummy = ["something random", {}]
100
166
  resource.save
101
167
  resource_dup = resource.dup
102
- ResourceFooWithState.find("fred").should == resource_dup
168
+ @resource_class_with_state.find("fred").should == resource_dup
103
169
  end
104
170
 
105
171
  it "should be deletable" do
106
- ResourceFoo.persist_to(Hash.new, "")
107
- resource = ResourceFoo.new
172
+ resource = @resource_class.new
108
173
  resource.key = "fred"
109
174
  resource.save
110
175
  lambda{resource.delete}.should_not raise_error
111
176
  end
112
177
 
113
178
  it "should save a new state when asked" do
114
- ResourceFooWithState.persist_to(Hash.new, "")
115
- resource = ResourceFooWithState.new
179
+ resource = @resource_class_with_state.new
116
180
  resource.key = "fred"
117
181
 
118
182
  resource.dummy = ["something random", {}]
@@ -123,24 +187,26 @@ describe "A class that includes HashPersistent::Resource" do
123
187
  resource.save
124
188
  resource_dup_2 = resource.dup
125
189
 
126
- ResourceFooWithState.find("fred").should_not == resource_dup_1
127
- ResourceFooWithState.find("fred").should == resource_dup_2
190
+ @resource_class_with_state.find("fred").should_not == resource_dup_1
191
+ @resource_class_with_state.find("fred").should == resource_dup_2
128
192
  end
129
193
  end
130
194
 
131
195
  context "(an instance that has been saved and then deleted)" do
196
+ before(:each) do
197
+ @resource_class = ResourceFoo.persist_to({}, "")
198
+ end
199
+
132
200
  it "should not be findable via its key" do
133
- ResourceFoo.persist_to(Hash.new, "")
134
- resource = ResourceFoo.new
201
+ resource = @resource_class.new
135
202
  resource.key = "fred"
136
203
  resource.save
137
204
  resource.delete
138
- ResourceFoo.find("fred").should == nil
205
+ @resource_class.find("fred").should == nil
139
206
  end
140
207
 
141
208
  it "should not complain when deleted" do
142
- ResourceFoo.persist_to(Hash.new, "")
143
- resource = ResourceFoo.new
209
+ resource = @resource_class.new
144
210
  resource.key = "fred"
145
211
  resource.save
146
212
  resource.delete
@@ -149,157 +215,104 @@ describe "A class that includes HashPersistent::Resource" do
149
215
  end
150
216
 
151
217
  context "(use of prefix to namespace keys)" do
218
+ before(:each) do
219
+ @resource_class = ResourceFoo.persist_to({}, "a_random_namespace::")
220
+ end
221
+
152
222
  it "should (transparently) prepend the supplied prefix to the key of the saved instance" do
153
- store = Hash.new
154
- ResourceFoo.persist_to(store, "a_random_namespace::")
155
- resource = ResourceFoo.new
223
+ resource = @resource_class.new
156
224
  resource.key = "fred"
157
225
  resource.save
158
- store.should_not have_key("fred")
159
- store.should have_key("a_random_namespace::fred")
226
+ @resource_class.store.should_not have_key("fred")
227
+ @resource_class.store.should have_key("a_random_namespace::fred")
160
228
  end
161
229
 
162
230
  it "should find instances when using a namespace, using only the key" do
163
- store = Hash.new
164
- ResourceFoo.persist_to(store, "a_random_namespace::")
165
- resource = ResourceFoo.new
231
+ resource = @resource_class.new
166
232
  resource.key = "fred"
167
233
  resource.save
168
- ResourceFoo.find("fred").should_not == nil
234
+ @resource_class.find("fred").should_not == nil
169
235
  end
170
236
 
171
237
  it "should not find instances when mistakenly given a namespaced key" do
172
- store = Hash.new
173
- ResourceFoo.persist_to(store, "a_random_namespace::")
174
- resource = ResourceFoo.new
238
+ resource = @resource_class.new
175
239
  resource.key = "fred"
176
240
  resource.save
177
- ResourceFoo.find("a_random_namespace::fred").should == nil
241
+ @resource_class.find("a_random_namespace::fred").should == nil
178
242
  end
179
243
 
180
244
  it "should correctly delete an instance from the store when using a prefix" do
181
- store = Hash.new
182
- ResourceFoo.persist_to(store, "a_random_namespace::")
183
- resource = ResourceFoo.new
245
+ resource = @resource_class.new
184
246
  resource.key = "fred"
185
247
  resource.save
186
248
  resource.delete
187
- ResourceFoo.find("fred").should == nil
249
+ @resource_class.find("fred").should == nil
250
+ @resource_class.store.should == {}
188
251
  end
189
252
  end
190
253
 
191
254
  context "(use of store)" do
192
255
  it "should correctly delete items from the store" do
193
- store = Hash.new
194
- ResourceFoo.persist_to(store, "")
195
- resource_1 = ResourceFoo.new
256
+ @resource_class = ResourceFoo.persist_to({}, "")
257
+ resource_1 = @resource_class.new
196
258
  resource_1.key = "fred"
197
259
  resource_1.save
198
260
 
199
- resource_2 = ResourceFoo.new
261
+ resource_2 = @resource_class.new
200
262
  resource_2.key = "barney"
201
263
  resource_2.save
202
- store.should_not == Hash.new
264
+ @resource_class.store.should_not == {}
203
265
 
204
266
  resource_1.delete
267
+ @resource_class.store.should_not == {}
268
+
205
269
  resource_2.delete
206
- store.should == Hash.new
270
+ @resource_class.store.should == {}
207
271
  end
208
272
  end
209
-
273
+
210
274
  context "(use of restricted hash api)" do
211
275
  it "should use only the restricted hash api provided by moneta" do
212
276
  lambda {
213
- ResourceFooWithState.persist_to(Dummy_RestrictedHash.new, "prefix::")
214
- resource_1 = ResourceFooWithState.new
277
+ @resource_class = ResourceFooWithState.persist_to(Dummy_RestrictedHash.new, "prefix::")
278
+ resource_1 = @resource_class.new
215
279
  resource_1.key = "fred"
216
280
  resource_1.dummy = ["barney"]
217
281
  resource_1.save
218
- ResourceFooWithState.find("fred").delete
282
+ @resource_class.find("fred").delete
219
283
  }.should_not raise_error
220
284
  end
221
285
  end
222
-
223
- context "(default store)" do
224
- it "should function with a vdefault store/prefix if none is supplied" do
225
- # This is implicitly tested elsewhere. Which makes this test documentation, I guess
226
- resource_1 = ResourceFooOnlyUsedOnce.new
227
- resource_1.key = "fred"
228
- resource_1.dummy = ["barney"]
229
- resource_1.save
230
- ResourceFooOnlyUsedOnce.find("fred").should == resource_1.dup
231
- lambda {ResourceFooOnlyUsedOnce.find("fred").delete}.should_not raise_error
232
- end
233
- end
234
-
235
- context "(multiple classes using module)" do
236
- # TODO: should check the callbacks here? Seems over the top...
237
- it "should not cross-contaminate classes that include the module" do
238
- store_1 = Hash.new
239
- ResourceFoo.persist_to(store_1, "")
240
- store_2 = Hash.new
241
- ResourceFooWithState.persist_to(store_2, "prefix::")
242
-
243
- store_1.should == Hash.new
244
- store_2.should == Hash.new
245
-
246
- resource_1 = ResourceFoo.new
247
- resource_1.key = "1"
248
- resource_1.save
249
-
250
- store_1.should_not == Hash.new
251
- store_2.should == Hash.new
252
- store_1.should have_key("1")
253
- store_1.should_not have_key("prefix::1")
254
-
255
- resource_1.delete
256
-
257
- store_1.should == Hash.new
258
- store_2.should == Hash.new
259
-
260
- resource_2 = ResourceFooWithState.new
261
- resource_2.key = "2"
262
- resource_2.save
263
-
264
- store_1.should == Hash.new
265
- store_2.should_not == Hash.new
266
- store_2.should have_key("prefix::2")
267
- store_2.should_not have_key("2")
268
-
269
- resource_2.delete
270
-
271
- store_1.should == Hash.new
272
- store_2.should == Hash.new
273
- end
274
- end
275
286
 
276
287
  context "(callbacks)" do
277
288
  it "should allow a class level callback to be set and retrieved for save events" do
278
- ResourceFoo.on_save.should == nil
279
- lambda{ResourceFoo.on_save do
289
+ @resource_class = ResourceFoo.persist_to({}, "")
290
+ @resource_class.on_save.should == nil
291
+
292
+ @resource_class.on_save do
280
293
  "thing"
281
- end}.should_not raise_error
282
- ResourceFoo.on_save.call.should == "thing"
283
- lambda{ResourceFoo.on_save(1)}.should raise_error
294
+ end
295
+ @resource_class.on_save.call.should == "thing"
284
296
  end
285
297
 
286
298
  it "should allow a class level callback to be set and retrieved for delete events" do
287
- ResourceFoo.on_delete.should == nil
288
- lambda{ResourceFoo.on_delete do
299
+ @resource_class = ResourceFoo.persist_to({}, "")
300
+ @resource_class.on_delete.should == nil
301
+ @resource_class.on_delete do
289
302
  "thing"
290
- end}.should_not raise_error
291
- ResourceFoo.on_delete.call.should == "thing"
292
- lambda{ResourceFoo.on_delete(1)}.should raise_error
303
+ end
304
+ @resource_class.on_delete.call.should == "thing"
293
305
  end
294
306
 
295
307
  it "should yield an instance to the save callback when the instance is saved" do
308
+ @resource_class = ResourceFoo.persist_to({}, "")
296
309
  yielded_instance = nil
297
- ResourceFoo.on_save do |yielded|
310
+ @resource_class.on_save do |yielded|
298
311
  yielded_instance = yielded
299
312
  end
300
313
 
301
- instance = ResourceFoo.new
302
- instance.key = "1"
314
+ instance = @resource_class.new
315
+ instance.key = "fah"
303
316
  instance.save
304
317
 
305
318
  yielded_instance.should_not == nil
@@ -307,13 +320,14 @@ describe "A class that includes HashPersistent::Resource" do
307
320
  end
308
321
 
309
322
  it "should yield an instance to the delete callback when the instance is deleted" do
323
+ @resource_class = ResourceFoo.persist_to({}, "")
310
324
  yielded_instance = nil
311
- ResourceFoo.on_delete do |yielded|
325
+ @resource_class.on_delete do |yielded|
312
326
  yielded_instance = yielded
313
327
  end
314
328
 
315
- instance = ResourceFoo.new
316
- instance.key = "1"
329
+ instance = @resource_class.new
330
+ instance.key = "bah"
317
331
  instance.save
318
332
  instance.delete
319
333
 
@@ -321,5 +335,21 @@ describe "A class that includes HashPersistent::Resource" do
321
335
  yielded_instance.should == instance
322
336
  end
323
337
 
338
+ it "should maintain separate callbacks for each created subclass" do
339
+ @resource_class_1 = ResourceFoo.persist_to({}, "")
340
+ @resource_class_2 = ResourceFoo.persist_to({}, "")
341
+
342
+ @resource_class_1.on_save do "on_save_1" end
343
+ @resource_class_1.on_delete do "on_delete_1" end
344
+
345
+ @resource_class_2.on_save do "on_save_2" end
346
+ @resource_class_2.on_delete do "on_delete_2" end
347
+
348
+ @resource_class_1.on_delete.call.should == "on_delete_1"
349
+ @resource_class_1.on_save.call.should == "on_save_1"
350
+
351
+ @resource_class_2.on_delete.call.should == "on_delete_2"
352
+ @resource_class_2.on_save.call.should == "on_save_2"
353
+ end
324
354
  end
325
355
  end
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.2.2
4
+ version: 0.3.1
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-02 00:00:00 -07:00
12
+ date: 2009-06-04 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -64,7 +64,7 @@ rubyforge_project:
64
64
  rubygems_version: 1.2.0
65
65
  signing_key:
66
66
  specification_version: 3
67
- summary: Library of base classes to simplify persisting objects in a moneta store
67
+ summary: Library of base classes to simplify persisting objects and collections to a moneta store
68
68
  test_files:
69
69
  - spec/collection_spec.rb
70
70
  - spec/counter_spec.rb