kissifer-hash-persistent 0.2.2 → 0.3.1

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