mongoose 0.1.0 → 0.1.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.
@@ -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