mongo_mapper-unstable 2010.1.6 → 2010.1.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/VERSION +1 -1
  2. data/lib/mongo_mapper/descendant_appends.rb +44 -0
  3. data/lib/mongo_mapper/document.rb +54 -98
  4. data/lib/mongo_mapper/embedded_document.rb +28 -348
  5. data/lib/mongo_mapper/finder_options.rb +15 -33
  6. data/lib/mongo_mapper/plugins/associations/base.rb +121 -0
  7. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +28 -0
  8. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +23 -0
  9. data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
  10. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +49 -0
  11. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +139 -0
  12. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  13. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +117 -0
  14. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
  15. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
  16. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
  17. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +66 -0
  18. data/lib/mongo_mapper/plugins/associations/proxy.rb +118 -0
  19. data/lib/mongo_mapper/plugins/associations.rb +104 -0
  20. data/lib/mongo_mapper/plugins/callbacks.rb +65 -0
  21. data/lib/mongo_mapper/plugins/clone.rb +13 -0
  22. data/lib/mongo_mapper/plugins/descendants.rb +16 -0
  23. data/lib/mongo_mapper/plugins/dirty.rb +119 -0
  24. data/lib/mongo_mapper/plugins/equality.rb +11 -0
  25. data/lib/mongo_mapper/plugins/identity_map.rb +66 -0
  26. data/lib/mongo_mapper/plugins/inspect.rb +14 -0
  27. data/lib/mongo_mapper/plugins/keys.rb +295 -0
  28. data/lib/mongo_mapper/plugins/logger.rb +17 -0
  29. data/lib/mongo_mapper/plugins/pagination.rb +85 -0
  30. data/lib/mongo_mapper/plugins/rails.rb +45 -0
  31. data/lib/mongo_mapper/plugins/serialization.rb +109 -0
  32. data/lib/mongo_mapper/plugins/validations.rb +48 -0
  33. data/lib/mongo_mapper/plugins.rb +19 -0
  34. data/lib/mongo_mapper/support.rb +36 -15
  35. data/lib/mongo_mapper.rb +23 -22
  36. data/performance/read_write.rb +52 -0
  37. data/specs.watchr +23 -2
  38. data/test/functional/associations/test_belongs_to_proxy.rb +1 -1
  39. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +58 -39
  40. data/test/functional/associations/test_many_embedded_proxy.rb +103 -69
  41. data/test/functional/test_dirty.rb +1 -1
  42. data/test/functional/test_document.rb +25 -25
  43. data/test/functional/test_embedded_document.rb +66 -63
  44. data/test/functional/test_identity_map.rb +233 -0
  45. data/test/functional/test_modifiers.rb +14 -0
  46. data/test/functional/test_string_id_compatibility.rb +4 -4
  47. data/test/functional/test_validations.rb +13 -0
  48. data/test/models.rb +0 -39
  49. data/test/test_helper.rb +8 -2
  50. data/test/unit/associations/test_base.rb +1 -1
  51. data/test/unit/associations/test_proxy.rb +3 -3
  52. data/test/unit/test_descendant_appends.rb +71 -0
  53. data/test/unit/test_document.rb +35 -46
  54. data/test/unit/test_embedded_document.rb +218 -271
  55. data/test/unit/{test_key.rb → test_keys.rb} +0 -0
  56. data/test/unit/test_pagination.rb +10 -2
  57. data/test/unit/test_plugins.rb +42 -0
  58. data/test/unit/test_rails.rb +123 -0
  59. data/test/unit/{test_serializations.rb → test_serialization.rb} +0 -0
  60. data/test/unit/test_support.rb +10 -6
  61. data/test/unit/test_time_zones.rb +2 -2
  62. metadata +44 -31
  63. data/lib/mongo_mapper/associations/base.rb +0 -119
  64. data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +0 -26
  65. data/lib/mongo_mapper/associations/belongs_to_proxy.rb +0 -21
  66. data/lib/mongo_mapper/associations/collection.rb +0 -19
  67. data/lib/mongo_mapper/associations/in_array_proxy.rb +0 -137
  68. data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +0 -26
  69. data/lib/mongo_mapper/associations/many_documents_proxy.rb +0 -115
  70. data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +0 -31
  71. data/lib/mongo_mapper/associations/many_embedded_proxy.rb +0 -54
  72. data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +0 -11
  73. data/lib/mongo_mapper/associations/one_proxy.rb +0 -64
  74. data/lib/mongo_mapper/associations/proxy.rb +0 -116
  75. data/lib/mongo_mapper/associations.rb +0 -78
  76. data/lib/mongo_mapper/callbacks.rb +0 -61
  77. data/lib/mongo_mapper/dirty.rb +0 -117
  78. data/lib/mongo_mapper/key.rb +0 -36
  79. data/lib/mongo_mapper/mongo_mapper.rb +0 -125
  80. data/lib/mongo_mapper/pagination.rb +0 -66
  81. data/lib/mongo_mapper/rails_compatibility/document.rb +0 -15
  82. data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +0 -28
  83. data/lib/mongo_mapper/serialization.rb +0 -54
  84. data/lib/mongo_mapper/serializers/json_serializer.rb +0 -48
  85. data/lib/mongo_mapper/validations.rb +0 -39
  86. data/test/functional/test_rails_compatibility.rb +0 -25
@@ -593,7 +593,15 @@ class DocumentTest < Test::Unit::TestCase
593
593
  end
594
594
 
595
595
  should "allow to use custom methods to assign properties" do
596
- person = RealPerson.new(:realname => 'David')
596
+ klass = Doc do
597
+ key :name, String
598
+
599
+ def realname=(value)
600
+ self.name = value
601
+ end
602
+ end
603
+
604
+ person = klass.new(:realname => 'David')
597
605
  person.save
598
606
  person.reload.name.should == 'David'
599
607
  end
@@ -713,17 +721,12 @@ class DocumentTest < Test::Unit::TestCase
713
721
  end
714
722
  end
715
723
 
716
- should "insert document" do
724
+ should "insert invalid document" do
717
725
  doc = @document.new
726
+ doc.expects(:valid?).never
718
727
  doc.save(:validate => false)
719
728
  @document.count.should == 1
720
729
  end
721
-
722
- should "work with false passed to save" do
723
- doc = @document.new
724
- doc.save(false)
725
- @document.count.should == 1
726
- end
727
730
  end
728
731
 
729
732
  context "#save (with options)" do
@@ -956,11 +959,19 @@ class DocumentTest < Test::Unit::TestCase
956
959
 
957
960
  context "timestamping" do
958
961
  setup do
959
- @document.timestamps!
962
+ @klass = Doc do
963
+ set_collection_name 'users'
964
+
965
+ key :first_name, String
966
+ key :last_name, String
967
+ key :age, Integer
968
+ key :date, Date
969
+ end
970
+ @klass.timestamps!
960
971
  end
961
972
 
962
973
  should "set created_at and updated_at on create" do
963
- doc = @document.new(:first_name => 'John', :age => 27)
974
+ doc = @klass.new(:first_name => 'John', :age => 27)
964
975
  doc.created_at.should be(nil)
965
976
  doc.updated_at.should be(nil)
966
977
  doc.save
@@ -970,7 +981,7 @@ class DocumentTest < Test::Unit::TestCase
970
981
 
971
982
  should "not overwrite created_at if it already exists" do
972
983
  original_created_at = 1.month.ago
973
- doc = @document.new(:first_name => 'John', :age => 27, :created_at => original_created_at)
984
+ doc = @klass.new(:first_name => 'John', :age => 27, :created_at => original_created_at)
974
985
  doc.created_at.to_i.should == original_created_at.to_i
975
986
  doc.updated_at.should be_nil
976
987
  doc.save
@@ -979,7 +990,7 @@ class DocumentTest < Test::Unit::TestCase
979
990
  end
980
991
 
981
992
  should "set updated_at on field update but leave created_at alone" do
982
- doc = @document.create(:first_name => 'John', :age => 27)
993
+ doc = @klass.create(:first_name => 'John', :age => 27)
983
994
  old_created_at = doc.created_at
984
995
  old_updated_at = doc.updated_at
985
996
  doc.first_name = 'Johnny'
@@ -993,12 +1004,12 @@ class DocumentTest < Test::Unit::TestCase
993
1004
  end
994
1005
 
995
1006
  should "set updated_at on document update but leave created_at alone" do
996
- doc = @document.create(:first_name => 'John', :age => 27)
1007
+ doc = @klass.create(:first_name => 'John', :age => 27)
997
1008
  old_created_at = doc.created_at
998
1009
  old_updated_at = doc.updated_at
999
1010
 
1000
1011
  Timecop.freeze(Time.now + 5.seconds) do
1001
- @document.update(doc._id, { :first_name => 'Johnny' })
1012
+ @klass.update(doc._id, { :first_name => 'Johnny' })
1002
1013
  end
1003
1014
 
1004
1015
  doc = doc.reload
@@ -1094,16 +1105,6 @@ class DocumentTest < Test::Unit::TestCase
1094
1105
  @instance.reload.object_id.should == @instance.object_id
1095
1106
  end
1096
1107
  end
1097
-
1098
- context "Saving a document with a custom id" do
1099
- should "clear custom id flag when saved" do
1100
- @document.key :_id, String
1101
- doc = @document.new(:id => '1234')
1102
- doc.using_custom_id?.should be_true
1103
- doc.save.should be_true
1104
- doc.using_custom_id?.should be_false
1105
- end
1106
- end
1107
1108
 
1108
1109
  context "Loading a document from the database with keys that are not defined" do
1109
1110
  setup do
@@ -1164,7 +1165,6 @@ class DocumentTest < Test::Unit::TestCase
1164
1165
  should "work with :index shortcut when defining key" do
1165
1166
  @document.key :father, String, :index => true
1166
1167
  MongoMapper.ensure_indexes!
1167
-
1168
1168
  @document.should have_index('father_1')
1169
1169
  end
1170
1170
  end
@@ -3,21 +3,29 @@ require 'models'
3
3
 
4
4
  class EmbeddedDocumentTest < Test::Unit::TestCase
5
5
  def setup
6
- @document = Doc do
7
- set_collection_name 'users'
6
+ @klass = Doc do
8
7
  key :first_name, String
9
8
  key :last_name, String
10
9
  end
10
+
11
+ @pet_klass = EDoc do
12
+ key :name, String
13
+ end
14
+
15
+ @klass.many :pets, :class => @pet_klass
16
+
17
+ @address_class = EDoc do
18
+ key :city, String
19
+ key :state, String
20
+ end
11
21
  end
12
22
 
13
23
  context "Saving a document with an embedded document" do
14
24
  setup do
15
- @document.class_eval do
16
- key :foo, Address
17
- end
25
+ @klass.key :foo, @address_class
18
26
 
19
- @address = Address.new(:city => 'South Bend', :state => 'IN')
20
- @doc = @document.new(:foo => @address)
27
+ @address = @address_class.new(:city => 'South Bend', :state => 'IN')
28
+ @doc = @klass.new(:foo => @address)
21
29
  end
22
30
 
23
31
  should "embed embedded document" do
@@ -42,27 +50,25 @@ class EmbeddedDocumentTest < Test::Unit::TestCase
42
50
 
43
51
  context "new?" do
44
52
  setup do
45
- @document.class_eval do
46
- key :foo, Address
47
- end
53
+ @klass.key :foo, @address_class
48
54
  end
49
55
 
50
56
  should "be new until document is saved" do
51
- address = Address.new(:city => 'South Bend', :state => 'IN')
52
- doc = @document.new(:foo => address)
57
+ address = @address_class.new(:city => 'South Bend', :state => 'IN')
58
+ doc = @klass.new(:foo => address)
53
59
  address.new?.should == true
54
60
  end
55
61
 
56
62
  should "not be new after document is saved" do
57
- address = Address.new(:city => 'South Bend', :state => 'IN')
58
- doc = @document.new(:foo => address)
63
+ address = @address_class.new(:city => 'South Bend', :state => 'IN')
64
+ doc = @klass.new(:foo => address)
59
65
  doc.save
60
66
  doc.foo.new?.should == false
61
67
  end
62
68
 
63
69
  should "not be new when document is read back" do
64
- address = Address.new(:city => 'South Bend', :state => 'IN')
65
- doc = @document.new(:foo => address)
70
+ address = @address_class.new(:city => 'South Bend', :state => 'IN')
71
+ doc = @klass.new(:foo => address)
66
72
  doc.save
67
73
 
68
74
  doc = doc.reload
@@ -70,53 +76,50 @@ class EmbeddedDocumentTest < Test::Unit::TestCase
70
76
  end
71
77
  end
72
78
 
73
- context "save" do
74
- should "save the root document" do
75
- person = RealPerson.create
76
-
77
- pet = Pet.new :name => 'sparky'
78
- person.pets << pet
79
- pet.save
80
-
81
- person = person.reload
82
- person.pets.first.should == pet
83
- end
79
+ should "be able to save" do
80
+ person = @klass.create
84
81
 
85
- should "save new keys" do
86
- person = RealPerson.new
87
- person[:new_attribute] = 'foobar'
88
- person.save
89
-
90
- person = person.reload
91
- person.new_attribute.should == 'foobar'
92
- end
82
+ pet = @pet_klass.new(:name => 'sparky')
83
+ person.pets << pet
84
+ pet.should be_new
85
+ pet.save
86
+ pet.should_not be_new
87
+
88
+ person.reload
89
+ person.pets.first.should == pet
93
90
  end
94
91
 
95
- context "update_attributes" do
96
- should "save the root document" do
97
- person = RealPerson.create
98
-
99
- pet = Pet.new(:name => 'sparky')
100
- person.pets << pet
101
- pet.save
102
-
103
- person = person.reload
104
- pet = person.pets.first
105
- pet.update_attributes :name => 'koda'
106
-
107
- person = person.reload
108
- person.pets.first._id.should == pet._id
109
- person.pets.first.name.should == 'koda'
110
- end
111
- end
112
-
113
- context "update_attributes!" do
114
- should "pass the attributes to self.attributes" do
115
- person = RealPerson.create
116
- attributes = { :foo => 'bar' }
117
- person.expects(:attributes=).with(attributes)
118
- person.expects(:save!)
119
- person.update_attributes!(attributes)
120
- end
121
- end
122
- end
92
+ should "be able to dynamically add new keys and save" do
93
+ person = @klass.create
94
+
95
+ pet = @pet_klass.new(:name => 'sparky', :crazy_key => 'crazy')
96
+ person.pets << pet
97
+ pet.save
98
+
99
+ person.reload
100
+ person.pets.first.crazy_key.should == 'crazy'
101
+ end
102
+
103
+ should "be able to update_attributes" do
104
+ pet = @pet_klass.new(:name => 'sparky')
105
+ person = @klass.create(:pets => [pet])
106
+ person.reload
107
+ pet = person.pets.first
108
+
109
+ pet.update_attributes(:name => 'koda').should be_true
110
+ person.reload
111
+ person.pets.first._id.should == pet._id
112
+ person.pets.first.name.should == 'koda'
113
+ end
114
+
115
+ should "be able to update_attributes!" do
116
+ person = @klass.create(:pets => [@pet_klass.new(:name => 'sparky')])
117
+ person.reload
118
+ pet = person.pets.first
119
+
120
+ attributes = {:name => 'koda'}
121
+ pet.expects(:attributes=).with(attributes)
122
+ pet.expects(:save!)
123
+ pet.update_attributes!(attributes)
124
+ end
125
+ end
@@ -0,0 +1,233 @@
1
+ require 'test_helper'
2
+
3
+ class IdentityMapTest < Test::Unit::TestCase
4
+ def assert_in_map(resource)
5
+ resource.identity_map.keys.should include(resource.identity_map_key)
6
+ mapped_resource = resource.identity_map[resource.identity_map_key]
7
+ resource.object_id.should == mapped_resource.object_id
8
+ end
9
+
10
+ def assert_not_in_map(resource)
11
+ resource.identity_map.keys.should_not include(resource.identity_map_key)
12
+ end
13
+
14
+ context "Document" do
15
+ setup do
16
+ @person_class = Doc('Person') do
17
+ key :name, String
18
+ plugin MongoMapper::Plugins::IdentityMap
19
+ end
20
+
21
+ @post_class = Doc('Post') do
22
+ key :title, String
23
+ plugin MongoMapper::Plugins::IdentityMap
24
+ end
25
+
26
+ @person_class.identity_map = {}
27
+ @post_class.identity_map = {}
28
+ end
29
+
30
+ should "default identity map to hash" do
31
+ Doc() do
32
+ plugin MongoMapper::Plugins::IdentityMap
33
+ end.identity_map.should == {}
34
+ end
35
+
36
+ should "share identity map with other classes" do
37
+ map = @post_class.identity_map
38
+ map.object_id.should == @person_class.identity_map.object_id
39
+ end
40
+
41
+ should "have identity map key that is always unique per document and class" do
42
+ person = @person_class.new
43
+ person.identity_map_key.should == "Person:#{person.id}"
44
+ @person_class.identity_map_key(person.id).should == person.identity_map_key
45
+
46
+ post = @post_class.new
47
+ post.identity_map_key.should == "Post:#{post.id}"
48
+ @post_class.identity_map_key(post.id).should == post.identity_map_key
49
+
50
+ person.identity_map_key.should_not == post.identity_map_key
51
+ end
52
+
53
+ should "add key to map when saved" do
54
+ person = @person_class.new
55
+ assert_not_in_map(person)
56
+ person.save.should be_true
57
+ assert_in_map(person)
58
+ end
59
+
60
+ should "remove key from map when deleted" do
61
+ person = @person_class.create(:name => 'Fred')
62
+ assert_in_map(person)
63
+ person.destroy
64
+ assert_not_in_map(person)
65
+ end
66
+
67
+ context "#load" do
68
+ setup do
69
+ @id = Mongo::ObjectID.new
70
+ end
71
+
72
+ should "add document to map with _id key as symbol" do
73
+ loaded = @person_class.load({:_id => @id, :name => 'Frank'})
74
+ assert_in_map(loaded)
75
+ end
76
+
77
+ should "add document to map with _id key as string" do
78
+ loaded = @person_class.load({'_id' => @id, :name => 'Frank'})
79
+ assert_in_map(loaded)
80
+ end
81
+
82
+ should "add document to map with id key as symbol" do
83
+ loaded = @person_class.load({:id => @id, :name => 'Frank'})
84
+ assert_in_map(loaded)
85
+ end
86
+
87
+ should "add document to map with id key as string" do
88
+ loaded = @person_class.load({'id' => @id, :name => 'Frank'})
89
+ assert_in_map(loaded)
90
+ end
91
+
92
+ should "return document if already in map" do
93
+ first_load = @person_class.load({:_id => @id, :name => 'Frank'})
94
+ @person_class.identity_map.expects(:[]=).never
95
+ second_load = @person_class.load({:_id => @id, :name => 'Frank'})
96
+ first_load.object_id.should == second_load.object_id
97
+ end
98
+ end
99
+
100
+ context "#find (with one id)" do
101
+ context "for object not in map" do
102
+ setup do
103
+ @person = @person_class.create(:name => 'Fred')
104
+ @person_class.identity_map.clear
105
+ end
106
+
107
+ should "query the database" do
108
+ Mongo::Collection.any_instance.expects(:find_one).once
109
+ @person_class.find(@person.id)
110
+ end
111
+
112
+ should "add object to map" do
113
+ assert_not_in_map(@person)
114
+ found_person = @person_class.find(@person.id)
115
+ assert_in_map(found_person)
116
+ end
117
+ end
118
+
119
+ context "for object in map" do
120
+ setup do
121
+ @person = @person_class.create(:name => 'Fred')
122
+ end
123
+
124
+ should "not query database" do
125
+ Mongo::Collection.any_instance.expects(:find).never
126
+ Mongo::Collection.any_instance.expects(:find_one).never
127
+ @person_class.find(@person.id)
128
+ end
129
+
130
+ should "return exact object" do
131
+ assert_in_map(@person)
132
+ found_person = @person_class.find(@person.id)
133
+ found_person.object_id.should == @person.object_id
134
+ end
135
+ end
136
+ end
137
+
138
+ context "#find (with multiple ids)" do
139
+ should "add all documents to map" do
140
+ person1 = @person_class.create(:name => 'Fred')
141
+ person2 = @person_class.create(:name => 'Bill')
142
+ person3 = @person_class.create(:name => 'Jesse')
143
+ @person_class.identity_map.clear
144
+
145
+ people = @person_class.find(person1.id, person2.id, person3.id)
146
+ people.each { |person| assert_in_map(person) }
147
+ end
148
+
149
+ should "add missing documents to map and return existing ones" do
150
+ person1 = @person_class.create(:name => 'Fred')
151
+ @person_class.identity_map.clear
152
+ person2 = @person_class.create(:name => 'Bill')
153
+ person3 = @person_class.create(:name => 'Jesse')
154
+
155
+ assert_not_in_map(person1)
156
+ assert_in_map(person2)
157
+ assert_in_map(person3)
158
+
159
+ people = @person_class.find(person1.id, person2.id, person3.id)
160
+ assert_in_map(people.first) # making sure one that wasn't mapped now is
161
+ assert_in_map(person2)
162
+ assert_in_map(person3)
163
+ end
164
+ end
165
+
166
+ context "#first" do
167
+ context "for object not in map" do
168
+ setup do
169
+ @person = @person_class.create(:name => 'Fred')
170
+ @person_class.identity_map.clear
171
+ end
172
+
173
+ should "query the database" do
174
+ Mongo::Collection.any_instance.expects(:find_one).once
175
+ @person_class.first(:_id => @person.id)
176
+ end
177
+
178
+ should "add object to map" do
179
+ assert_not_in_map(@person)
180
+ found_person = @person_class.first(:_id => @person.id)
181
+ assert_in_map(found_person)
182
+ end
183
+ end
184
+
185
+ context "for object in map" do
186
+ setup do
187
+ @person = @person_class.create(:name => 'Fred')
188
+ end
189
+
190
+ should "not query database" do
191
+ Mongo::Collection.any_instance.expects(:find).never
192
+ Mongo::Collection.any_instance.expects(:find_one).never
193
+ @person_class.first(:_id => @person.id)
194
+ end
195
+
196
+ should "return exact object" do
197
+ assert_in_map(@person)
198
+ found_person = @person_class.first(:_id => @person.id)
199
+ found_person.object_id.should == @person.object_id
200
+ end
201
+ end
202
+ end
203
+
204
+ context "#all" do
205
+ should "add all documents to map" do
206
+ person1 = @person_class.create(:name => 'Fred')
207
+ person2 = @person_class.create(:name => 'Bill')
208
+ person3 = @person_class.create(:name => 'Jesse')
209
+ @person_class.identity_map.clear
210
+
211
+ people = @person_class.all(:_id => [person1.id, person2.id, person3.id])
212
+ people.each { |person| assert_in_map(person) }
213
+ end
214
+
215
+ should "add missing documents to map and return existing ones" do
216
+ person1 = @person_class.create(:name => 'Fred')
217
+ @person_class.identity_map.clear
218
+ person2 = @person_class.create(:name => 'Bill')
219
+ person3 = @person_class.create(:name => 'Jesse')
220
+
221
+ assert_not_in_map(person1)
222
+ assert_in_map(person2)
223
+ assert_in_map(person3)
224
+
225
+ people = @person_class.all(:_id => [person1.id, person2.id, person3.id])
226
+ assert_in_map(people.first) # making sure one that wasn't mapped now is
227
+ assert_in_map(person2)
228
+ assert_in_map(person3)
229
+ end
230
+ end
231
+
232
+ end
233
+ end
@@ -235,4 +235,18 @@ class ModifierTest < Test::Unit::TestCase
235
235
  page2.reload
236
236
  page.tags.should == %w(foo)
237
237
  end
238
+
239
+ should "be able to remove the last element the array" do
240
+ page = @page_class.create(:title => 'Home', :tags => %w(foo bar))
241
+ @page_class.pop(page.id, :tags => 1)
242
+ page.reload
243
+ page.tags.should == %w(foo)
244
+ end
245
+
246
+ should "be able to remove the first element of the array" do
247
+ page = @page_class.create(:title => 'Home', :tags => %w(foo bar))
248
+ @page_class.pop(page.id, :tags => -1)
249
+ page.reload
250
+ page.tags.should == %w(bar)
251
+ end
238
252
  end
@@ -19,7 +19,7 @@ class StringIdCompatibilityTest < Test::Unit::TestCase
19
19
 
20
20
  @task_class.belongs_to :project, :class => @project_class
21
21
  @project_class.many :notes, :class => @note_class
22
- @project_class.many :tasks, :class => @task_class, :foreign_key => 'project_id'
22
+ @project_class.many :tasks, :class => @task_class, :foreign_key => 'project_id', :order => :position.asc
23
23
  end
24
24
 
25
25
  should "assign correct _id for documents" do
@@ -55,9 +55,9 @@ class StringIdCompatibilityTest < Test::Unit::TestCase
55
55
  end
56
56
 
57
57
  should "be able to associate records" do
58
- t1 = @task_class.new(:body => 'First task')
59
- t2 = @task_class.new(:body => 'Second task')
60
- t3 = @task_class.new(:body => 'Third task')
58
+ t1 = @task_class.new(:body => 'First task', :position => 1)
59
+ t2 = @task_class.new(:body => 'Second task', :position => 2)
60
+ t3 = @task_class.new(:body => 'Third task', :position => 3)
61
61
  project = @project_class.create(:name => 'MM', :tasks => [t1, t2, t3])
62
62
 
63
63
  project = project.reload
@@ -186,6 +186,19 @@ class ValidationsTest < Test::Unit::TestCase
186
186
  doc2.should_not have_error_on(:name)
187
187
  end
188
188
 
189
+ should "allow multiple nil entries if :allow_nil => true" do
190
+ document = Doc do
191
+ key :name
192
+ validates_uniqueness_of :name, :allow_nil => :true
193
+ end
194
+
195
+ doc = document.new('name' => nil)
196
+ doc.save.should be_true
197
+
198
+ doc2 = document.new('name' => nil)
199
+ doc2.should_not have_error_on(:name)
200
+ end
201
+
189
202
  should "allow entries that differ only in case by default" do
190
203
  document = Doc do
191
204
  key :name
data/test/models.rb CHANGED
@@ -109,12 +109,6 @@ class Answer
109
109
  key :body, String
110
110
  end
111
111
 
112
- module PeopleExtensions
113
- def find_by_name(name)
114
- detect { |p| p.name == name }
115
- end
116
- end
117
-
118
112
  module CollaboratorsExtensions
119
113
  def top
120
114
  first
@@ -126,9 +120,7 @@ class Project
126
120
 
127
121
  key :name, String
128
122
 
129
- many :people, :extend => PeopleExtensions
130
123
  many :collaborators, :extend => CollaboratorsExtensions
131
-
132
124
  many :statuses, :order => 'position' do
133
125
  def open
134
126
  all(:name => %w(New Assigned))
@@ -163,37 +155,6 @@ class Status
163
155
  belongs_to :target, :polymorphic => true
164
156
  end
165
157
 
166
- class RealPerson
167
- include MongoMapper::Document
168
-
169
- key :room_id, ObjectId
170
- key :name, String
171
-
172
- belongs_to :room
173
-
174
- many :pets
175
-
176
- def realname=(n)
177
- self.name = n
178
- end
179
- end
180
-
181
- class Person
182
- include MongoMapper::EmbeddedDocument
183
-
184
- key :name, String
185
- key :child, Person
186
-
187
- many :pets
188
- end
189
-
190
- class Pet
191
- include MongoMapper::EmbeddedDocument
192
-
193
- key :name, String
194
- key :species, String
195
- end
196
-
197
158
  class Media
198
159
  include MongoMapper::EmbeddedDocument
199
160
 
data/test/test_helper.rb CHANGED
@@ -38,10 +38,16 @@ class Test::Unit::TestCase
38
38
  klass
39
39
  end
40
40
 
41
- def EDoc(&block)
41
+ def EDoc(name=nil, &block)
42
42
  Class.new do
43
43
  include MongoMapper::EmbeddedDocument
44
- instance_eval(&block) if block_given?
44
+
45
+ if name
46
+ class_eval "def self.name; '#{name}' end"
47
+ class_eval "def self.to_s; '#{name}' end"
48
+ end
49
+
50
+ class_eval(&block) if block_given?
45
51
  end
46
52
  end
47
53
  end
@@ -4,7 +4,7 @@ require 'models'
4
4
  class FooMonster; end
5
5
 
6
6
  class AssociationBaseTest < Test::Unit::TestCase
7
- include MongoMapper::Associations
7
+ include MongoMapper::Plugins::Associations
8
8
 
9
9
  should "initialize with type and name" do
10
10
  base = Base.new(:many, :foos)
@@ -1,14 +1,14 @@
1
1
  require 'test_helper'
2
2
 
3
- class FakeNilProxy < MongoMapper::Associations::Proxy
3
+ class FakeNilProxy < MongoMapper::Plugins::Associations::Proxy
4
4
  def find_target; nil end
5
5
  end
6
6
 
7
- class FakeBlankProxy < MongoMapper::Associations::Proxy
7
+ class FakeBlankProxy < MongoMapper::Plugins::Associations::Proxy
8
8
  def find_target; '' end
9
9
  end
10
10
 
11
- class FakeProxy < MongoMapper::Associations::Proxy
11
+ class FakeProxy < MongoMapper::Plugins::Associations::Proxy
12
12
  def find_target
13
13
  [1, 2]
14
14
  end