kyoto_record 0.0.1 → 0.0.2

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/kyoto_record.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "kyoto_record"
3
- s.version = "0.0.1"
3
+ s.version = "0.0.2"
4
4
  s.summary = "Persist your classes in Kyoto Cabinet."
5
5
  s.description = "\"KyotoRecord\": Kyoto Cabinet wrapper for Ruby binding. Scannable. Indexable. A programming interface made for babies."
6
6
  s.homepage = "http://github.com/thirdreplicator/kyoto_record"
data/kyoto_record.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # kyoto_record.rb
1
2
  require 'kyotocabinet'
2
3
 
3
4
  module KyotoRecord
@@ -9,6 +10,8 @@ module KyotoRecord
9
10
  module Cabinet
10
11
  include KyotoCabinet
11
12
 
13
+ DATA_DIR = File.dirname(__FILE__) + '/data'
14
+
12
15
  def find(id)
13
16
  value = @db.get(id)
14
17
  if value
@@ -18,6 +21,16 @@ module KyotoRecord
18
21
  end
19
22
  end
20
23
 
24
+ def delete(id)
25
+ @db.remove(id)
26
+ end
27
+
28
+ def delete_all
29
+ scan(1, 1/0.0) do |obj|
30
+ obj.delete
31
+ end
32
+ end
33
+
21
34
  def scan(start_key=nil, limit=1/0.0, &block)
22
35
  cur = @db.cursor
23
36
  i = 0
@@ -52,16 +65,16 @@ module KyotoRecord
52
65
  end
53
66
 
54
67
  # Utilities
55
- def open_db(base_name)
56
- Dir.mkdir('data') if !Dir.exists?('data')
68
+ def open_db
69
+ Dir.mkdir(DATA_DIR) if !Dir.exists?(DATA_DIR)
57
70
  db = DB::new
58
- unless db.open("./data/#{base_name}.kch", DB::OWRITER | DB::OCREATE)
71
+ unless db.open(data_file, DB::OWRITER | DB::OCREATE)
59
72
  STDERR.printf("open error: %s\n", db.error)
60
73
  end
61
74
  db
62
75
  end
63
76
 
64
- def close_db(base_name)
77
+ def close_db
65
78
  unless @db.close
66
79
  STDERR.printf("close error: %s\n", db.error)
67
80
  end
@@ -70,9 +83,9 @@ module KyotoRecord
70
83
  # Utilities
71
84
 
72
85
  def set(k,v)
73
- @db.set(k, Marshal.dump(v))
86
+ set_error(k,v) unless @db.set(k, Marshal.dump(v))
74
87
  end
75
-
88
+
76
89
  def get(k)
77
90
  val = @db.get(k)
78
91
  Marshal.load(val) if val
@@ -97,6 +110,16 @@ module KyotoRecord
97
110
  def class_name
98
111
  @class_name ||= self.to_s
99
112
  end
113
+
114
+ def data_file
115
+ "#{DATA_DIR}/#{@base_name}.kch"
116
+ end
117
+
118
+ def set_error(k,v)
119
+ STDERR.printf("set error for (k,v)=(%s, %s): %s\n", k, v, @db.error)
120
+ raise @db.error
121
+ end
122
+
100
123
  end # Cabinet
101
124
 
102
125
  # Reuse the Cabinet module to make indexes of attributes.
@@ -112,7 +135,7 @@ module KyotoRecord
112
135
  @klass = klass
113
136
  @attr = attribute
114
137
  @base_name = klass.to_s + "_" + attribute.to_s
115
- @db = open_db(@base_name)
138
+ @db = open_db
116
139
  end
117
140
  end # class Index
118
141
 
@@ -121,35 +144,33 @@ module KyotoRecord
121
144
  include Cabinet
122
145
 
123
146
  def attr_kyoto( *attrs )
124
- @db = open_db(class_name)
147
+ @base_name = class_name
148
+ @db = open_db
125
149
 
126
150
  @attrs ||= {}
127
151
  @indices ||= {}
128
152
 
129
- # Don't redefine it if it was already defined.
130
- if !self.respond_to?(:id)
131
- # a general setter
132
- define_method :set_attr do |k, v|
133
- @values[k] = v
153
+ # a general setter
154
+ define_method :set_attr do |k, v|
155
+ @values[k] = v
156
+ end
157
+
158
+ # a general getter
159
+ define_method :get_attr do |k|
160
+ @values[k]
161
+ end
162
+
163
+ def define_getter_and_setter(attr)
164
+ define_method :"#{attr}".to_s do
165
+ @values[attr]
134
166
  end
135
167
 
136
- # a general getter
137
- define_method :get_attr do |k|
138
- @values[k]
139
- end
140
-
141
- def define_getter_and_setter(attr)
142
- define_method :"#{attr}".to_s do
143
- @values[attr]
144
- end
145
-
146
- define_method :"#{attr}=".to_s do |val|
147
- set_attr(attr, val)
148
- end
149
- end
168
+ define_method :"#{attr}=".to_s do |val|
169
+ set_attr(attr, val)
170
+ end
171
+ end
150
172
 
151
- define_getter_and_setter(:id)
152
- end # if
173
+ define_getter_and_setter(:id)
153
174
 
154
175
  # In case multiple attributes were passed in, let's loop over each one.
155
176
  attrs.each do |attr|
@@ -189,14 +210,23 @@ EOM
189
210
  def save
190
211
  if !id
191
212
  # TODO: use KyotoCabinet::DB#increment
192
- id = self.class.last_id + 1
213
+ self.id = self.class.last_id + 1
193
214
  self.class.last_id = id
194
215
  end
195
-
216
+
196
217
  write_indices(id)
197
218
  write_to_kyoto(id, self)
198
219
  end
199
220
 
221
+ def update(attr, value)
222
+ @values[attr] = value
223
+ save
224
+ end
225
+
226
+ def delete
227
+ self.class.delete(self.id)
228
+ end
229
+
200
230
  def write_indices(id)
201
231
  self.class.indices.each do |attr, index|
202
232
  index.set(@values[attr], id)
@@ -204,14 +234,11 @@ EOM
204
234
  end
205
235
 
206
236
  def write_to_kyoto(k, v)
207
- set_error(k,v) unless self.class.set(k, v)
237
+ self.class.set(k, v)
208
238
  end
209
239
 
210
240
  private
211
241
 
212
- def set_error(k,v)
213
- STDERR.printf("set error for (k,v)=(%s, %s): %s\n", k, v, kc.error)
214
- end
215
242
 
216
243
  end
217
244
 
data/kyoto_record_spec.rb CHANGED
@@ -19,13 +19,20 @@ describe 'KyotoRecord module' do
19
19
  File.exist?('./data/A.kch').should be_true
20
20
  end
21
21
 
22
- it "should retrieve 3 if 3 was saved into a kyoto attribute" do
22
+ it "find should return an instance of the enhanced user-defined class" do
23
23
  @a = A.new
24
24
  @a.x = 3
25
25
  @a.save
26
26
  A.find(1).should be_an_instance_of(A)
27
27
  end
28
28
 
29
+ it "should have an id after being saved." do
30
+ @a = A.new
31
+ @a.x = 3
32
+ @a.save
33
+ @a.id.should == 1
34
+ end
35
+
29
36
  it "should retrieve 3 if 3 was saved into a kyoto attribute" do
30
37
  @a = A.new
31
38
  @a.x = 3
@@ -47,6 +54,21 @@ describe 'KyotoRecord module' do
47
54
  A.find(1).x.should be_an_instance_of( Time )
48
55
  end
49
56
 
57
+ it "should be able to save 2 different objects using the same variable" do
58
+ a = A.new
59
+ a.x = "David"
60
+ a.save
61
+
62
+ a = A.new
63
+ a.x = "Bob"
64
+ a.save
65
+
66
+ A.find(1).x.should == "David"
67
+ A.find(1).id.should == 1
68
+ A.find(2).x.should == "Bob"
69
+ A.find(2).id.should == 2
70
+ end
71
+
50
72
  it "should have a last_id of nil if nothing has been saved yet." do
51
73
  A.last_id.should == 0
52
74
  end
@@ -108,7 +130,7 @@ describe 'KyotoRecord module' do
108
130
 
109
131
  describe "Iterating over the records." do
110
132
  before(:each) do
111
- # Insert 100 records
133
+ # Insert some records
112
134
  10.times do |i|
113
135
  a = A.new
114
136
  a.x = i+1
@@ -148,6 +170,7 @@ describe 'KyotoRecord module' do
148
170
  word.should == "56"
149
171
  end
150
172
  end
173
+
151
174
  describe "Indexing of attributes." do
152
175
  before(:each) do
153
176
  class A
@@ -170,6 +193,110 @@ describe 'KyotoRecord module' do
170
193
  A.find_by_username("David").username.should == "David"
171
194
  end
172
195
  end
196
+ describe "DELETE functionality" do
197
+ it "should be able to delete records by key (class utility function)" do
198
+ a = A.new
199
+ a.username = "David"
200
+ a.save
201
+ A.find(1).should_not be_nil
202
+ A.delete(1)
203
+ A.find(1).should be_nil
204
+ end
205
+
206
+ it "should be able to delete records by key (instance method)" do
207
+ a = A.new
208
+ a.username = "David"
209
+ a.save
210
+ A.find(1).should_not be_nil
211
+ a.delete
212
+ A.find(1).should be_nil
213
+ end
214
+ end
215
+
216
+ describe "UPDATE functionality" do
217
+ it "should be able to update just by saving over the existing one." do
218
+ a = A.new
219
+ a.username = "David"
220
+ a.save
221
+
222
+ # Loop him up.
223
+ a1 = A.find(1)
224
+ a1.username.should == "David"
225
+
226
+ # Modify him.
227
+ a1.username = "Bob"
228
+ a1.save
229
+
230
+ # Make sure he changed.
231
+ A.find(1).username.should == "Bob"
232
+ end
233
+
234
+ it "should be able to update with a instance method." do
235
+ a = A.new
236
+ a.username = "David"
237
+ a.save
238
+
239
+ A.find(1).update(:username, "Bob")
240
+ A.find(1).username.should == "Bob"
241
+ end
242
+
243
+ it "should be able to batch update by scanning over a range of ids." do
244
+ 10.times do |i|
245
+ a = A.new
246
+ a.username = i+1
247
+ a.save
248
+ end
249
+
250
+ A.scan(1,5) do |a|
251
+ a.update(:username, "Anonymous")
252
+ end
253
+
254
+ A.find(1).username.should == "Anonymous"
255
+ A.find(3).username.should == "Anonymous"
256
+ A.find(5).username.should == "Anonymous"
257
+ A.find(6).username.should == 6
258
+ A.find(7).username.should == 7
259
+ A.find(10).username.should == 10
260
+ end
261
+ end
262
+
263
+ describe "DROP the whole database" do
264
+ it "should be able to drop the whole database." do
265
+ a = A.new
266
+ a.username = "David"
267
+ a.save
268
+
269
+ a = A.new
270
+ a.username = "Bob"
271
+ a.save
272
+
273
+ A.find(1).username.should == "David"
274
+ A.find(2).username.should == "Bob"
275
+
276
+ A.delete_all
277
+
278
+ A.find(1).should be_nil
279
+ A.find(2).should be_nil
280
+ end
281
+
282
+ it "should be able to add more items after the database was dropped." do
283
+ a = A.new
284
+ a.username = "David"
285
+ a.save
286
+
287
+ A.find(1).username.should == "David"
288
+
289
+ A.delete_all
290
+
291
+ b = A.new
292
+ b.username = "Duck"
293
+ b.id.should be_nil
294
+ b.save
295
+
296
+ b.id.should == 2
297
+ A.find(2).should_not be_nil
298
+ end
299
+ end
173
300
 
174
301
  describe "Auxilliary functions" do
175
302
  it "should be able to know it's own name as a string" do
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: kyoto_record
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.1
5
+ version: 0.0.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - David Beckwith
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-03-02 00:00:00 -08:00
13
+ date: 2011-03-05 00:00:00 -08:00
14
14
  default_executable:
15
15
  dependencies: []
16
16