mongoose 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -67,7 +67,7 @@ class Table
67
67
  #-----------------------------------------------------------------------------
68
68
  def self.has_many(kind)
69
69
  table_name = Util.singularize(kind.to_s).to_sym
70
- class_name = Util.us_case_to_class_case(table_name.to_s)
70
+ class_name = Util.us_case_to_class_case(table_name)
71
71
  col = Util.col_name_for_class(self.to_s)
72
72
 
73
73
  define_method(kind.to_sym) do
@@ -82,7 +82,7 @@ class Table
82
82
  #-----------------------------------------------------------------------------
83
83
  def self.has_one(kind)
84
84
  table_name = kind.to_sym
85
- class_name = Util.us_case_to_class_case(table_name.to_s)
85
+ class_name = Util.us_case_to_class_case(table_name)
86
86
  col = Util.col_name_for_class(self.to_s)
87
87
 
88
88
  define_method(kind.to_sym) do
@@ -95,7 +95,8 @@ class Table
95
95
  # Table.belongs_to
96
96
  #-----------------------------------------------------------------------------
97
97
  def self.belongs_to(kind)
98
- class_name = Util.us_case_to_class_case(kind.to_sym)
98
+ table_name = kind.to_sym
99
+ class_name = Util.us_case_to_class_case(table_name)
99
100
 
100
101
  define_method(kind) do
101
102
  klass = Object.const_get(class_name.to_s)
@@ -113,28 +114,14 @@ class Table
113
114
  # Table.last_id_used
114
115
  #-----------------------------------------------------------------------------
115
116
  def self.last_id_used
116
- self.db.tables[self][:last_id_used]
117
- end
118
-
119
- #-----------------------------------------------------------------------------
120
- # Table.last_id_used=
121
- #-----------------------------------------------------------------------------
122
- def self.last_id_used=(value)
123
- self.db.tables[self][:last_id_used] = value
117
+ self.class.read_header[:last_id_used]
124
118
  end
125
119
 
126
120
  #-----------------------------------------------------------------------------
127
121
  # Table.deleted_recs_counter
128
122
  #-----------------------------------------------------------------------------
129
123
  def self.deleted_recs_counter
130
- self.db.tables[self][:deleted_recs_counter]
131
- end
132
-
133
- #-----------------------------------------------------------------------------
134
- # Table.deleted_recs_counter=
135
- #-----------------------------------------------------------------------------
136
- def self.deleted_recs_counter=(value)
137
- self.db.tables[self][:deleted_recs_counter]=(value)
124
+ self.class.read_header[:deleted_recs_counter]
138
125
  end
139
126
 
140
127
  #-----------------------------------------------------------------------------
@@ -149,21 +136,16 @@ class Table
149
136
  # Table.write_header
150
137
  #-----------------------------------------------------------------------------
151
138
  def self.write_header(header)
152
- File.open(File.join(self.path, self.table_name.to_s + TBL_HDR_EXT), 'w') do |f|
153
- YAML.dump(header, f)
154
- end
139
+ File.open(File.join(self.path, self.table_name.to_s + TBL_HDR_EXT), 'w'
140
+ ) { |f| YAML.dump(header, f) }
155
141
  end
156
142
 
157
143
  #-----------------------------------------------------------------------------
158
144
  # Table.init_table
159
145
  #-----------------------------------------------------------------------------
160
146
  def self.init_table
161
-
162
147
  tbl_header = self.read_header
163
148
 
164
- self.last_id_used = tbl_header[:last_id_used]
165
- self.deleted_recs_counter = tbl_header[:deleted_recs_counter]
166
-
167
149
  self.read_header[:columns].each do |c|
168
150
  self.init_column(c[:name], c[:data_type], Object.full_const_get(c[:class])
169
151
  )
@@ -385,9 +367,7 @@ class Table
385
367
  # initialize
386
368
  #-----------------------------------------------------------------------------
387
369
  def initialize(*values)
388
- self.class.columns.zip(values).each do |c,v|
389
- send("#{c.name}=", v)
390
- end
370
+ self.class.columns.zip(values).each { |c,v| send("#{c.name}=", v) }
391
371
  end
392
372
 
393
373
  #-----------------------------------------------------------------------------
@@ -395,25 +375,23 @@ class Table
395
375
  #-----------------------------------------------------------------------------
396
376
  def save
397
377
  self.class.columns.each do |c|
378
+ # First checks to see if validates_presence_of was set in class def.
398
379
  raise "Value required for #{c.name}!" if respond_to?('required?') and \
399
380
  required?(c.name) and send(c.name).nil?
381
+ # Next checks to see if validates_presence_of was set in #add_column.
400
382
  raise "Value required for #{c.name}!" if c.required? and send(c.name).nil?
401
383
  end
402
384
 
385
+ # Add new record.
403
386
  if @id.nil?
404
- tbl_header = self.class.read_header
405
- self.class.last_id_used += 1
406
-
407
- append_record(self.class.last_id_used,
408
- self.class.column_names[1..-1].collect { |col_name| send(col_name) })
409
-
410
- @id = self.class.last_id_used
411
- tbl_header[:last_id_used] = self.class.last_id_used
412
- self.class.write_header(tbl_header)
387
+ id = increment_last_id_used
388
+ append_record(id, self.class.column_names[1..-1].collect { |col_name|
389
+ send(col_name) })
390
+ @id = id
391
+ # Update existing record.
413
392
  else
414
393
  update_record(@id, self.class.columns[1..-1].collect { |c| send(c.name) })
415
394
  end
416
-
417
395
  return true
418
396
  end
419
397
 
@@ -431,12 +409,16 @@ class Table
431
409
  raise IndexCorruptError, "Index ID does not match table ID!", caller \
432
410
  unless rec[1] == @id
433
411
 
412
+ # First array position of record is the deleted flag: true means deleted
434
413
  rec[0] = true
435
414
 
415
+ # Record is not actually deleted; it just has its deleted flag set to
416
+ # true.
436
417
  write_record(fptr, fpos_rec_start, Marshal.dump(rec))
437
418
  increment_deleted_recs_counter
438
419
  end
439
420
 
421
+ # Remove all index recs pointing to this record.
440
422
  self.class.columns.each_with_index do |c,i|
441
423
  if i == 0
442
424
  c.remove_index_rec(@id)
@@ -445,6 +427,7 @@ class Table
445
427
  end
446
428
  end
447
429
 
430
+ # Don't allow any more changes to this record.
448
431
  freeze
449
432
  end
450
433
 
@@ -463,9 +446,12 @@ class Table
463
446
  fptr.seek(0, IO::SEEK_END)
464
447
  fpos = fptr.tell
465
448
 
449
+ # Append record to end of file, making sure to add deleted flag and record
450
+ # id to front of record.
466
451
  fpos = write_record(fptr, 'end', Marshal.dump([false, id].concat(values)))
467
452
  end
468
453
 
454
+ # Update indexes with new record.
469
455
  self.class.columns.each_with_index do |c,i|
470
456
  if i == 0
471
457
  c.add_index_rec(id, fpos)
@@ -495,15 +481,25 @@ class Table
495
481
 
496
482
  old_rec_length = fptr.tell - fpos_rec_start
497
483
 
484
+ # If updates did not change record length, we can write it back out to
485
+ # the same spot in the file...
498
486
  if new_rec.length == old_rec_length
499
487
  write_record(fptr, fpos_rec_start, new_rec)
500
488
  else
501
- fpos = write_record(fptr, 'end', new_rec)
489
+ # Set deleted flag to true and update old rec position. Increment
490
+ # deleted records counter.
491
+ old_rec[0] = true
492
+ write_record(fptr, fpos_rec_start, Marshal.dump(old_rec))
502
493
  increment_deleted_recs_counter
494
+
495
+ # Append the updated record to the end of the file and update the
496
+ # record id index.
497
+ fpos = write_record(fptr, 'end', new_rec)
503
498
  self.class.columns[0].add_index_rec(id, fpos)
504
499
  end
505
500
  end
506
501
 
502
+ # Update all of the indexed columns with the updated record data.
507
503
  self.class.columns[1..-1].each do |c|
508
504
  unless temp_instance.send(c.name) == send(c.name)
509
505
  if c.indexed?
@@ -514,14 +510,24 @@ class Table
514
510
  end
515
511
  end
516
512
 
513
+ #-----------------------------------------------------------------------------
514
+ # increment_last_id_used
515
+ #-----------------------------------------------------------------------------
516
+ def increment_last_id_used
517
+ tbl_header = self.class.read_header
518
+ tbl_header[:last_id_used] += 1
519
+ self.class.write_header(tbl_header)
520
+ return tbl_header[:last_id_used]
521
+ end
522
+
517
523
  #-----------------------------------------------------------------------------
518
524
  # increment_deleted_recs_counter
519
525
  #-----------------------------------------------------------------------------
520
526
  def increment_deleted_recs_counter
521
527
  tbl_header = self.class.read_header
522
- self.class.deleted_recs_counter += 1
523
- tbl_header[:deleted_recs_counter] = self.class.deleted_recs_counter
528
+ tbl_header[:deleted_recs_counter] += 1
524
529
  self.class.write_header(tbl_header)
530
+ return tbl_header[:deleted_recs_counter]
525
531
  end
526
532
 
527
533
  #-----------------------------------------------------------------------------
@@ -551,7 +557,7 @@ class Collection
551
557
  end
552
558
 
553
559
  def each
554
- records.each { |rec| yield rec }
560
+ @records.each { |rec| yield rec }
555
561
  end
556
562
 
557
563
  def <<(rec)
@@ -563,6 +569,10 @@ class Collection
563
569
  def append(rec)
564
570
  self << rec
565
571
  end
572
+
573
+ def size
574
+ @records.size
575
+ end
566
576
  end
567
577
 
568
578
  end
@@ -37,7 +37,7 @@ end
37
37
  def self.class_name_for_col(name)
38
38
  us_case_to_class_case(name.sub(/_id\z/, ''))
39
39
  end
40
-
40
+
41
41
  end
42
42
 
43
43
  end
@@ -0,0 +1,139 @@
1
+ require 'test/unit'
2
+ require 'tmpdir'
3
+
4
+ begin
5
+ require 'rubygems'
6
+ require_gem 'Mongoose'
7
+ rescue LoadError
8
+ require 'mongoose'
9
+ end
10
+
11
+ class Pilot < Mongoose::Table
12
+ has_one :plane
13
+ has_many :flights
14
+ end
15
+
16
+ class Plane < Mongoose::Table
17
+ belongs_to :pilot
18
+ end
19
+
20
+ class Flight < Mongoose::Table
21
+ belongs_to :pilot
22
+ end
23
+
24
+ class TestRelations < Test::Unit::TestCase
25
+ def setup
26
+ @db = Mongoose::Database.new(:path => Dir.tmpdir)
27
+
28
+ @db.create_table(:pilot) do |tbl|
29
+ tbl.add_indexed_column(:pilot_name, :string)
30
+ tbl.add_column(:years_flying, :integer)
31
+ end
32
+
33
+ @db.create_table(:plane) do |tbl|
34
+ tbl.add_indexed_column(:plane_name, :string)
35
+ tbl.add_column(:country, :string)
36
+ tbl.add_indexed_column(:speed, :integer)
37
+ tbl.add_column(:range, :integer)
38
+ tbl.add_column(:pilot_id, :integer)
39
+ end
40
+
41
+ @db.create_table(:flight) do |tbl|
42
+ tbl.add_column(:origin, :string)
43
+ tbl.add_column(:destination, :string)
44
+ tbl.add_column(:pilot_id, :integer)
45
+ end
46
+
47
+ @doolittle = Pilot.new
48
+ @doolittle.pilot_name = 'Doolittle, James'
49
+ @doolittle.years_flying = 15
50
+ @doolittle.save
51
+
52
+ @amelia = Pilot.new
53
+ @amelia.pilot_name = 'Earhart, Amelia'
54
+ @amelia.years_flying = 10
55
+ @amelia.save
56
+
57
+ rec = Plane.new
58
+ rec.plane_name = 'P-51'
59
+ rec.country = 'USA'
60
+ rec.speed = 402
61
+ rec.range = 1205
62
+ rec.pilot_id = @doolittle.id
63
+ rec.save
64
+
65
+ rec = Plane.new
66
+ rec.plane_name = 'Spitfire'
67
+ rec.country = 'Great Britain'
68
+ rec.speed = 333
69
+ rec.range = 454
70
+ rec.pilot_id = @amelia.id
71
+ rec.save
72
+
73
+ rec = Flight.new
74
+ rec.pilot_id = @doolittle.id
75
+ rec.origin = 'Army'
76
+ rec.destination = 'Nowhere'
77
+ rec.save
78
+
79
+ rec = Flight.new
80
+ rec.pilot_id = @amelia.id
81
+ rec.origin = 'USA'
82
+ rec.destination = 'France'
83
+
84
+ rec.save
85
+ rec = Flight.new
86
+ rec.pilot_id = @amelia.id
87
+ rec.origin = 'USA'
88
+ rec.destination = 'Phillipines'
89
+ rec.save
90
+
91
+ rec = Flight.new
92
+ rec.pilot_id = @amelia.id
93
+ rec.origin = 'China'
94
+ rec.destination = 'Unknown'
95
+ rec.save
96
+ end
97
+
98
+ def teardown
99
+ @db.drop_table(:pilot)
100
+ @db.drop_table(:plane)
101
+ @db.drop_table(:flight)
102
+ @db.close
103
+ end
104
+
105
+ def test_has_one
106
+ assert_equal('P-51', @doolittle.plane.plane_name)
107
+ end
108
+
109
+ def test_has_many_001
110
+ assert_equal(3, @amelia.flights.size)
111
+ assert(@amelia.flights.any? {|f| f.destination == 'France'})
112
+ end
113
+
114
+ def test_has_many_002
115
+ rec = Flight.new
116
+ rec.pilot_id = @amelia.id
117
+ rec.origin = 'Tuscon'
118
+ rec.destination = 'Phoenix'
119
+ @amelia.flights << rec
120
+
121
+ assert(@amelia.flights.any? {|f| f.origin == 'Tuscon'})
122
+ end
123
+
124
+ def test_belongs_to_001
125
+ assert_equal('Earhart, Amelia', Plane.find(2).pilot.pilot_name)
126
+ assert_equal('Doolittle, James', Flight.find(1).pilot.pilot_name)
127
+ end
128
+
129
+ def test_belongs_to_002
130
+ red_baron = Pilot.new
131
+ red_baron.pilot_name = 'Baron, The Red'
132
+ red_baron.years_flying = 50
133
+ spitfire = Plane.find(:first) {|plane| plane.plane_name == 'Spitfire'}
134
+ spitfire.pilot = red_baron
135
+
136
+ assert('Baron, The Red', spitfire.pilot.pilot_name)
137
+ assert_equal('Spitfire', red_baron.plane.plane_name)
138
+ end
139
+ end
@@ -74,7 +74,17 @@ class TestTable < Test::Unit::TestCase
74
74
  assert_equal(1205, rec.range)
75
75
  end
76
76
 
77
- def test_update_record
77
+ def test_update_record_001
78
+ rec = Plane.find(2)
79
+ rec.country = 'England'
80
+ rec.save
81
+
82
+ rec = Plane.find(2)
83
+
84
+ assert_equal('England', rec.country)
85
+ end
86
+
87
+ def test_update_record_002
78
88
  rec = Plane.find(1)
79
89
  rec.speed = 405
80
90
  rec.save
@@ -84,14 +94,23 @@ class TestTable < Test::Unit::TestCase
84
94
  assert_equal(rec.speed, 405)
85
95
  end
86
96
 
87
- def test_find_001
97
+ def find_001
88
98
  rec = Plane.find(:first) { |plane| plane.name == 'P-51' }
89
99
 
90
100
  assert(rec.is_a?(Plane))
91
101
  assert_equal(rec.name, 'P-51')
102
+ end
103
+
104
+ def test_find_001
105
+ find_001
106
+
107
+ @db.close
108
+ @db = Mongoose::Database.new(:path => Dir.tmpdir)
109
+
110
+ find_001
92
111
  end
93
112
 
94
- def test_find_002
113
+ def find_002
95
114
  recs = Plane.find { |plane| plane.name == 'P-51' }
96
115
 
97
116
  assert_equal(recs.size, 1)
@@ -105,7 +124,16 @@ class TestTable < Test::Unit::TestCase
105
124
  assert_equal(recs[1].name, 'Spitfire')
106
125
  end
107
126
 
108
- def test_find_003
127
+ def test_find_002
128
+ find_002
129
+
130
+ @db.close
131
+ @db = Mongoose::Database.new(:path => Dir.tmpdir)
132
+
133
+ find_002
134
+ end
135
+
136
+ def find_003
109
137
  recs = Plane.find do |plane|
110
138
  plane.any do
111
139
  plane.country == 'USA'
@@ -135,7 +163,16 @@ class TestTable < Test::Unit::TestCase
135
163
  assert_equal(recs.first.name, 'P-51')
136
164
  end
137
165
 
138
- def test_find_004
166
+ def test_find_003
167
+ find_003
168
+
169
+ @db.close
170
+ @db = Mongoose::Database.new(:path => Dir.tmpdir)
171
+
172
+ find_003
173
+ end
174
+
175
+ def find_004
139
176
  recs = Plane.find { |plane| plane.name.one_of('P-51', 'ME-109') }
140
177
  assert_equal(recs.size, 2)
141
178
 
@@ -156,6 +193,15 @@ class TestTable < Test::Unit::TestCase
156
193
  assert_equal(2, recs.size)
157
194
  end
158
195
 
196
+ def test_find_004
197
+ find_004
198
+
199
+ @db.close
200
+ @db = Mongoose::Database.new(:path => Dir.tmpdir)
201
+
202
+ find_004
203
+ end
204
+
159
205
  def test_destroy
160
206
  rec = Plane.find(:first) { |plane| plane.name == 'P-51' }
161
207
  rec.destroy