mongodb-mongo_record 0.2 → 0.3

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/README.rdoc CHANGED
@@ -72,6 +72,15 @@ See MongoRecord::LogDevice. When running outside of the cloud (for example,
72
72
  during development), all log messages are echoed to $stderr which is normally
73
73
  the console.
74
74
 
75
+ == Credits
76
+ Jim Mulholland, jim at squeejee dot com
77
+ * Ability to save custom attributes not declared in the model
78
+ * Save and retrieve custom "_id" fields
79
+ * Find_each functionality
80
+ * Find_last based on the created_at field
81
+ * Assigning created_at and updated_at fields even if they are not declared
82
+ * Alias methods for "first", "last" and "all"
83
+
75
84
  == To Do
76
85
 
77
86
  * DBRefs
@@ -119,7 +119,7 @@ module MongoRecord
119
119
  # lower_case_with_underscores.
120
120
  def collection_name(coll_name)
121
121
  @coll_name = coll_name
122
- field(:_id, :_ns, :_update)
122
+ field(:_id, :_ns)
123
123
  end
124
124
 
125
125
  # Creates one or more collection fields. Each field will be saved to
@@ -287,10 +287,10 @@ module MongoRecord
287
287
  # is the same as
288
288
  # Person.find(:all).skip(10).limit(10).sort({:created_on => 1})
289
289
  #
290
-
291
-
292
- def find(*args)
293
- options = extract_options_from_args!(args)
290
+
291
+
292
+ def find(*args)
293
+ options = extract_options_from_args!(args)
294
294
  options.symbolize_keys!
295
295
  case args.first
296
296
  when :first
@@ -303,7 +303,7 @@ module MongoRecord
303
303
  find_from_ids(args, options)
304
304
  end
305
305
  end
306
-
306
+
307
307
  # Yields each record that was found by the find +options+. The find is
308
308
  # performed by find.
309
309
  #
@@ -313,20 +313,20 @@ module MongoRecord
313
313
  # person.party_all_night!
314
314
  # end
315
315
 
316
- def find_each(*args)
317
- options = extract_options_from_args!(args)
316
+ def find_each(*args)
317
+ options = extract_options_from_args!(args)
318
318
  options.symbolize_keys!
319
319
  find_every(options).each do |record|
320
- yield record
320
+ yield record
321
321
  end
322
322
  self
323
323
  end
324
-
324
+
325
325
  def all(*args)
326
326
  options = extract_options_from_args!(args)
327
327
  find_every(options)
328
328
  end
329
-
329
+
330
330
  def first(*args)
331
331
  # args = ([:first]<<args).flatten
332
332
  options = extract_options_from_args!(args)
@@ -362,10 +362,10 @@ module MongoRecord
362
362
  end
363
363
 
364
364
  def sum(column)
365
- x = self.find(:all, :select=>column)
365
+ x = self.find(:all, :select=>column)
366
366
  x.map {|p1| p1.followers_count}.compact.sum
367
367
  end
368
-
368
+
369
369
  # Deletes the record with the given id from the collection.
370
370
  def delete(id)
371
371
  collection.remove({:_id => id})
@@ -465,7 +465,7 @@ module MongoRecord
465
465
  # row = collection.find_first(criteria, :fields => fields)
466
466
  # (row.nil? || row['_id'] == nil) ? nil : self.new(row)
467
467
  # end
468
-
468
+
469
469
  def find_initial(options)
470
470
  options[:limit] = 1
471
471
  options[:order] = 'created_at asc'
@@ -483,7 +483,7 @@ module MongoRecord
483
483
  def find_every(options)
484
484
  options.symbolize_keys!
485
485
  criteria = criteria_from(options[:conditions], options[:criteria]).merge!(where_func(options[:where]))
486
-
486
+
487
487
  find_options = {}
488
488
  find_options[:fields] = fields_from(options[:select]) if options[:select]
489
489
  find_options[:limit] = options[:limit].to_i if options[:limit]
@@ -528,10 +528,10 @@ module MongoRecord
528
528
 
529
529
  def ids_clause(ids)
530
530
  #ids.length == 1 ? ids[0].to_oid : {'$in' => ids.collect{|id| id.to_oid}}
531
-
532
- if ids.length == 1
531
+
532
+ if ids.length == 1
533
533
  ids[0].is_a?(String) ? ids[0].to_oid : ids[0]
534
- else
534
+ else
535
535
  {'$in' => ids.collect{|id| id.is_a?(String) ? id.to_oid : id}}
536
536
  end
537
537
  end
@@ -577,7 +577,7 @@ module MongoRecord
577
577
  opts = criteria_from_hash(condition)
578
578
  else
579
579
  opts = {}
580
- end
580
+ end
581
581
  opts ||= {}
582
582
  criteria ||= {}
583
583
  opts.merge!(criteria)
@@ -771,7 +771,7 @@ module MongoRecord
771
771
 
772
772
  # Save self and returns true if the save was successful, false if not.
773
773
  def save
774
- create_or_update
774
+ create_or_update
775
775
  end
776
776
 
777
777
  # Save self and returns true if the save was successful and raises
@@ -789,14 +789,22 @@ module MongoRecord
789
789
  # database.
790
790
  def to_mongo_value
791
791
  h = {}
792
- # self.class.mongo_ivar_names.each {|iv| h[iv] = instance_variable_get("@#{iv}").to_mongo_value }
793
- mongo_values = self.instance_values
794
- # If the "_id" value is not set but an "id" value is, set "_id" equal to "id"
795
- if mongo_values["_id"].nil? && !mongo_values["id"].nil?
796
- mongo_values["_id"] = mongo_values["id"]
797
- end
798
- key_names = mongo_values.keys + self.class.subobjects.keys + self.class.arrays.keys
799
- key_names.each {|key| h[key] = instance_variable_get("@#{key}").to_mongo_value }
792
+ key_names = self.instance_values.keys
793
+ key_names.each {|key|
794
+ value = instance_variable_get("@#{key}").to_mongo_value
795
+ if value.instance_of? Hash and value["_ns"]
796
+ value = XGen::Mongo::Driver::DBRef.new(value["_ns"], value["_id"])
797
+ elsif value.instance_of? Array
798
+ value = value.map {|v|
799
+ if v.instance_of? Hash and v["_ns"]
800
+ XGen::Mongo::Driver::DBRef.new(v["_ns"], v["_id"])
801
+ else
802
+ v
803
+ end
804
+ }
805
+ end
806
+ h[key] = value
807
+ }
800
808
  h
801
809
  end
802
810
 
@@ -804,6 +812,7 @@ module MongoRecord
804
812
  def create
805
813
  create_date = self.instance_variable_defined?("@created_at") ? self.created_at : nil
806
814
  set_create_times(create_date)
815
+ @_ns = self.class.collection.name
807
816
  with_id = self.class.collection.insert(to_mongo_value)
808
817
  @_id = with_id['_id'] || with_id[:_id]
809
818
  with_id
@@ -817,7 +826,7 @@ module MongoRecord
817
826
  if self.class.collection.db.error?
818
827
  return false
819
828
  end
820
- self
829
+ self
821
830
  end
822
831
 
823
832
  # Remove self from the database and set @_id to nil. If self has no
@@ -839,12 +848,12 @@ module MongoRecord
839
848
  def [](attr_name)
840
849
  self.send(attr_name)
841
850
  end
842
-
851
+
843
852
  def []=(attr_name, value)
844
853
  self.class.field(attr_name)
845
854
  self.send(attr_name.to_s + '=', value)
846
855
  end
847
-
856
+
848
857
  def method_missing(sym, *args)
849
858
  if self.instance_variables.include?("@#{sym}")
850
859
  self.class.field(sym)
@@ -853,7 +862,7 @@ module MongoRecord
853
862
  super
854
863
  end
855
864
  end
856
-
865
+
857
866
  #--
858
867
  # ================================================================
859
868
  # These methods exist so we can plug in ActiveRecord validation, etc.
@@ -913,11 +922,19 @@ module MongoRecord
913
922
  def init_ivar(ivar_name, val)
914
923
  sym = ivar_name[1..-1].to_sym
915
924
  if self.class.subobjects.keys.include?(sym)
925
+ if val.instance_of? XGen::Mongo::Driver::DBRef
926
+ val = self.class.collection.db.dereference(val)
927
+ end
916
928
  instance_variable_set(ivar_name, self.class.subobjects[sym].new(val))
917
929
  elsif self.class.arrays.keys.include?(sym)
918
930
  klazz = self.class.arrays[sym]
919
931
  val = [val] unless val.kind_of?(Array)
920
- instance_variable_set(ivar_name, val.collect {|v| v.kind_of?(MongoRecord::Base) ? v : klazz.new(v)})
932
+ instance_variable_set(ivar_name, val.collect {|v|
933
+ if v.instance_of? XGen::Mongo::Driver::DBRef
934
+ v = self.class.collection.db.dereference(v)
935
+ end
936
+ v.kind_of?(MongoRecord::Base) ? v : klazz.new(v)
937
+ })
921
938
  else
922
939
  instance_variable_set(ivar_name, val)
923
940
  end
@@ -1,11 +1,11 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'mongo_record'
3
- s.version = '0.2'
3
+ s.version = '0.3'
4
4
  s.platform = Gem::Platform::RUBY
5
5
  s.summary = 'ActiveRecord-like models for the 10gen Mongo DB'
6
6
  s.description = 'MongoRecord is an ActiveRecord-like framework for the 10gen Mongo database. For more information about Mongo, see http://www.mongodb.org.'
7
7
 
8
- s.add_dependency('mongodb-mongo', ['>= 0.6.1'])
8
+ s.add_dependency('mongodb-mongo', ['>= 0.6.7'])
9
9
 
10
10
  s.require_paths = ['lib']
11
11
 
data/tests/test_mongo.rb CHANGED
@@ -164,7 +164,7 @@ class MongoTest < Test::Unit::TestCase
164
164
  def test_find_all
165
165
  assert_all_songs Track.find(:all).inject('') { |str, t| str + t.to_s }
166
166
  end
167
-
167
+
168
168
  def test_find_using_hash
169
169
  str = Track.find(:all, :conditions => {:album => 'Aliens Ate My Buick'}).inject('') { |str, t| str + t.to_s }
170
170
  assert_match(/song: The Ability to Swing/, str)
@@ -271,11 +271,9 @@ class MongoTest < Test::Unit::TestCase
271
271
  assert_equal "Budapest by Blimp:Europa and the Pirate Twins:Garden Of Earthly Delights:King For A Day:The Ability to Swing:The Mayor Of Simpleton",
272
272
  tracks.collect {|t| t.song }.join(':')
273
273
 
274
- # TODO this should work, but the database does not yet sort this properly
275
- # tracks = Track.find(:all, :order => "artist desc, song")
276
- # assert_not_nil tracks
277
- # assert_equal "Garden Of Earthly Delights:King For A Day:The Mayor Of Simpleton:Budapest by Blimp:Europa and the Pirate Twins:The Ability to Swing",
278
- # tracks.collect {|t| t.song }.join(':')
274
+ tracks = Track.find(:all, :order => "artist desc, song")
275
+ assert_not_nil tracks
276
+ assert_equal "Garden Of Earthly Delights:King For A Day:The Mayor Of Simpleton:Budapest by Blimp:Europa and the Pirate Twins:The Ability to Swing", tracks.collect {|t| t.song }.join(':')
279
277
  end
280
278
 
281
279
  def test_delete
@@ -560,34 +558,54 @@ class MongoTest < Test::Unit::TestCase
560
558
  assert_equal s.created_on, s.updated_on
561
559
  end
562
560
 
563
- # # TODO dbrefs are not yet implemented
564
- # # This reproduces a bug where DBRefs weren't being created properly because
565
- # # the MongoRecord::Base objects weren't storing the magic _ns, _update, and
566
- # # other values set by the database.
567
- # def test_db_ref
568
- # s = Student.new(:name => 'Spongebob Squarepants', :address => @spongebob_addr)
569
- # s.save
561
+ # This reproduces a bug where DBRefs weren't being created properly because
562
+ # the MongoRecord::Base objects weren't storing _ns
563
+ def test_db_ref
564
+ s = Student.new(:name => 'Spongebob Squarepants', :address => @spongebob_addr)
565
+ s.save
566
+
567
+ @course1.save
568
+ assert_not_nil @course1.id
569
+ assert_not_nil @course1["_ns"]
570
+
571
+ s.add_score(@course1.id, 3.5)
572
+ s.save
573
+
574
+ score = s.scores.first
575
+ assert_not_nil score
576
+ assert_equal @course1.name, score.for_course.name
570
577
 
571
- # @course1.save
572
- # assert_not_nil @course1.id
578
+ # Now change the name of @course1 and see the student's score's course
579
+ # name change.
580
+ @course1.name = 'changed'
581
+ @course1.save
573
582
 
574
- # s.add_score(@course1.id, 3.5)
575
- # s.save # This used to blow up
583
+ s = Student.find(:first, :conditions => "name = 'Spongebob Squarepants'")
584
+ assert_not_nil s
585
+ assert_equal 1, s.scores.length
586
+ assert_equal 'changed', s.scores.first.for_course.name
576
587
 
577
- # score = s.scores.first
578
- # assert_not_nil score
579
- # assert_equal @course1.name, score.for_course.name
580
588
 
581
- # # Now change the name of @course1 and see the student's score's course
582
- # # name change.
583
- # @course1.name = 'changed'
584
- # @course1.save
589
+ # Now try with has_many
590
+ score.save
591
+ s.scores = [score]
592
+ s.save
585
593
 
586
- # s = Student.find(:first, :conditions => "name = 'Spongebob Squarepants'")
587
- # assert_not_nil s
588
- # assert_equal 1, s.scores.length
589
- # assert_equal 'changed', s.scores.first.for_course.name
590
- # end
594
+ assert_equal 3.5, s.scores.first.grade
595
+
596
+ s = Student.find(:first, :conditions => "name = 'Spongebob Squarepants'")
597
+ assert_not_nil s
598
+ assert_equal 1, s.scores.length
599
+ assert_equal 3.5, s.scores.first.grade
600
+
601
+ score.grade = 4.0
602
+ score.save
603
+
604
+ s = Student.find(:first, :conditions => "name = 'Spongebob Squarepants'")
605
+ assert_not_nil s
606
+ assert_equal 1, s.scores.length
607
+ assert_equal 4.0, s.scores.first.grade
608
+ end
591
609
 
592
610
  def test_subobjects_have_no_ids
593
611
  @spongebob_addr.id
@@ -637,7 +655,7 @@ class MongoTest < Test::Unit::TestCase
637
655
  assert_match /undefined method \`foobar\' for Track:Class/, ex.to_s
638
656
  end
639
657
  end
640
-
658
+
641
659
  def test_adding_custom_attributes
642
660
  s = Student.new(:silly_name => 'Yowza!')
643
661
  s.save
@@ -653,22 +671,22 @@ class MongoTest < Test::Unit::TestCase
653
671
  assert_match(/song: The Mayor Of Simpleton/, str)
654
672
  assert_match(/song: King For A Day/, str)
655
673
  end
656
-
657
-
658
- #################
659
-
660
-
674
+
675
+
676
+ #################
677
+
678
+
661
679
  def test_find_all_alias
662
680
  assert_all_songs Track.all.inject('') { |str, t| str + t.to_s }
663
- end
664
-
681
+ end
682
+
665
683
  def test_find_first_alias
666
684
  t = Track.first
667
685
  assert t.kind_of?(Track)
668
686
  str = t.to_s
669
687
  assert_match(/artist: [^,]+,/, str, "did not find non-empty artist name")
670
688
  end
671
-
689
+
672
690
  def test_find_last
673
691
  c = Course.new(:name=>"History")
674
692
  c.save
@@ -698,7 +716,7 @@ class MongoTest < Test::Unit::TestCase
698
716
  assert_equal(count, Playlist.count)
699
717
  end
700
718
 
701
-
719
+
702
720
  def test_update_attributes
703
721
  opts = {:artist => 'Bon Jovi', :album => 'Slippery When Wet', :song => 'Livin On A Prayer'}
704
722
  track = Track.new
@@ -706,7 +724,7 @@ class MongoTest < Test::Unit::TestCase
706
724
  t = Track.find_by_artist("Bon Jovi")
707
725
  assert_equal(t.album, "Slippery When Wet")
708
726
  end
709
-
727
+
710
728
  def test_update_attributes_for_custom_attributes
711
729
  opts = {:artist => 'The Outfield', :album => 'Play Deep', :song => 'Your Love', :year => 1986}
712
730
  playlist = Playlist.new
@@ -714,7 +732,7 @@ class MongoTest < Test::Unit::TestCase
714
732
  p = Playlist.find_by_artist("The Outfield")
715
733
  assert_equal(p.year, 1986)
716
734
  end
717
-
735
+
718
736
  def test_custom_id
719
737
  track = Track.new
720
738
  track.id = 123
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongodb-mongo_record
3
3
  version: !ruby/object:Gem::Version
4
- version: "0.2"
4
+ version: "0.3"
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Menard
@@ -21,7 +21,7 @@ dependencies:
21
21
  requirements:
22
22
  - - ">="
23
23
  - !ruby/object:Gem::Version
24
- version: 0.6.1
24
+ version: 0.6.7
25
25
  version:
26
26
  description: MongoRecord is an ActiveRecord-like framework for the 10gen Mongo database. For more information about Mongo, see http://www.mongodb.org.
27
27
  email: mongodb-user@googlegroups.com