jnunemaker-mongomapper 0.3.1 → 0.3.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.
Files changed (37) hide show
  1. data/History +11 -0
  2. data/VERSION +1 -1
  3. data/lib/mongomapper/associations/base.rb +5 -2
  4. data/lib/mongomapper/associations/belongs_to_polymorphic_proxy.rb +1 -2
  5. data/lib/mongomapper/associations/belongs_to_proxy.rb +3 -3
  6. data/lib/mongomapper/associations/many_documents_proxy.rb +85 -0
  7. data/lib/mongomapper/associations/many_embedded_polymorphic_proxy.rb +2 -3
  8. data/lib/mongomapper/associations/many_embedded_proxy.rb +2 -4
  9. data/lib/mongomapper/associations/many_polymorphic_proxy.rb +11 -0
  10. data/lib/mongomapper/associations/many_proxy.rb +1 -50
  11. data/lib/mongomapper/associations/proxy.rb +1 -1
  12. data/lib/mongomapper/document.rb +5 -12
  13. data/lib/mongomapper/embedded_document.rb +21 -2
  14. data/lib/mongomapper/key.rb +2 -1
  15. data/lib/mongomapper/serializers/json_serializer.rb +15 -0
  16. data/lib/mongomapper.rb +17 -10
  17. data/mongomapper.gemspec +17 -4
  18. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +39 -0
  19. data/test/functional/associations/test_belongs_to_proxy.rb +35 -0
  20. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +131 -0
  21. data/test/functional/associations/test_many_embedded_proxy.rb +106 -0
  22. data/test/functional/associations/test_many_polymorphic_proxy.rb +259 -0
  23. data/test/functional/associations/test_many_proxy.rb +236 -0
  24. data/test/functional/test_associations.rb +22 -467
  25. data/test/functional/test_document.rb +76 -19
  26. data/test/functional/test_pagination.rb +2 -3
  27. data/test/models.rb +16 -0
  28. data/test/test_helper.rb +1 -1
  29. data/test/unit/serializers/test_json_serializer.rb +69 -16
  30. data/test/unit/test_association_base.rb +5 -0
  31. data/test/unit/test_document.rb +14 -4
  32. data/test/unit/test_embedded_document.rb +46 -21
  33. data/test/unit/test_key.rb +5 -0
  34. data/test/unit/test_mongo_id.rb +2 -2
  35. data/test/unit/test_rails_compatibility.rb +3 -3
  36. metadata +16 -3
  37. data/lib/mongomapper/associations/array_proxy.rb +0 -6
@@ -0,0 +1,131 @@
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class ManyEmbeddedPolymorphicProxyTest < Test::Unit::TestCase
5
+ def setup
6
+ clear_all_collections
7
+ end
8
+
9
+ should "default reader to empty array" do
10
+ catalog = Catalog.new
11
+ catalog.medias.should == []
12
+ end
13
+
14
+ should "allow adding to association like it was an array" do
15
+ catalog = Catalog.new
16
+ catalog.medias << Video.new
17
+ catalog.medias.push Video.new
18
+ catalog.medias.size.should == 2
19
+ end
20
+
21
+ should "be able to replace the association" do
22
+ catalog = Catalog.new
23
+ catalog.medias = [Video.new("file" => "video.mpg", "length" => 3600)]
24
+ catalog.save.should be_true
25
+
26
+ from_db = Catalog.find(catalog.id)
27
+ from_db.medias.size.should == 1
28
+ from_db.medias[0].file.should == "video.mpg"
29
+ end
30
+
31
+ should "store different associations" do
32
+ catalog = Catalog.new
33
+ catalog.medias = [
34
+ Video.new("file" => "video.mpg", "length" => 3600),
35
+ Music.new("file" => "music.mp3", "bitrate" => "128kbps"),
36
+ Image.new("file" => "image.png", "width" => 800, "height" => 600)
37
+ ]
38
+ catalog.save.should be_true
39
+
40
+ from_db = Catalog.find(catalog.id)
41
+ from_db.medias.size.should == 3
42
+ from_db.medias[0].file.should == "video.mpg"
43
+ from_db.medias[0].length.should == 3600
44
+ from_db.medias[1].file.should == "music.mp3"
45
+ from_db.medias[1].bitrate.should == "128kbps"
46
+ from_db.medias[2].file.should == "image.png"
47
+ from_db.medias[2].width.should == 800
48
+ from_db.medias[2].height.should == 600
49
+ end
50
+
51
+ context "With modularized models" do
52
+ should "set associations correctly" do
53
+ fleet_attributes = {
54
+ "name" => "My Fleet",
55
+ "transports" => [
56
+ {"_type" => "TrModels::Ambulance", "license_plate" => "GGG123", "icu" => true},
57
+ {"_type" => "TrModels::Car", "license_plate" => "ABC123", "model" => "VW Golf", "year" => 2001},
58
+ {"_type" => "TrModels::Car", "license_plate" => "DEF123", "model" => "Honda Accord", "year" => 2008},
59
+ ]
60
+ }
61
+
62
+ fleet = TrModels::Fleet.new(fleet_attributes)
63
+ fleet.transports.size.should == 3
64
+ fleet.transports[0].class.should == TrModels::Ambulance
65
+ fleet.transports[0].license_plate.should == "GGG123"
66
+ fleet.transports[0].icu.should be_true
67
+ fleet.transports[1].class.should == TrModels::Car
68
+ fleet.transports[1].license_plate.should == "ABC123"
69
+ fleet.transports[1].model.should == "VW Golf"
70
+ fleet.transports[1].year.should == 2001
71
+ fleet.transports[2].class.should == TrModels::Car
72
+ fleet.transports[2].license_plate.should == "DEF123"
73
+ fleet.transports[2].model.should == "Honda Accord"
74
+ fleet.transports[2].year.should == 2008
75
+ fleet.save.should be_true
76
+
77
+ from_db = TrModels::Fleet.find(fleet.id)
78
+ from_db.transports.size.should == 3
79
+ from_db.transports[0].license_plate.should == "GGG123"
80
+ from_db.transports[0].icu.should be_true
81
+ from_db.transports[1].license_plate.should == "ABC123"
82
+ from_db.transports[1].model.should == "VW Golf"
83
+ from_db.transports[1].year.should == 2001
84
+ from_db.transports[2].license_plate.should == "DEF123"
85
+ from_db.transports[2].model.should == "Honda Accord"
86
+ from_db.transports[2].year.should == 2008
87
+ end
88
+
89
+ should "default reader to empty array" do
90
+ fleet = TrModels::Fleet.new
91
+ fleet.transports.should == []
92
+ end
93
+
94
+ should "allow adding to association like it was an array" do
95
+ fleet = TrModels::Fleet.new
96
+ fleet.transports << TrModels::Car.new
97
+ fleet.transports.push TrModels::Bus.new
98
+ fleet.transports.size.should == 2
99
+ end
100
+
101
+ should "be able to replace the association" do
102
+ fleet = TrModels::Fleet.new
103
+ fleet.transports = [TrModels::Car.new("license_plate" => "DCU2013", "model" => "Honda Civic")]
104
+ fleet.save.should be_true
105
+
106
+ from_db = TrModels::Fleet.find(fleet.id)
107
+ from_db.transports.size.should == 1
108
+ from_db.transports[0].license_plate.should == "DCU2013"
109
+ end
110
+
111
+ should "store different associations" do
112
+ fleet = TrModels::Fleet.new
113
+ fleet.transports = [
114
+ TrModels::Car.new("license_plate" => "ABC1223", "model" => "Honda Civic", "year" => 2003),
115
+ TrModels::Bus.new("license_plate" => "XYZ9090", "max_passengers" => 51),
116
+ TrModels::Ambulance.new("license_plate" => "HDD3030", "icu" => true)
117
+ ]
118
+ fleet.save.should be_true
119
+
120
+ from_db = TrModels::Fleet.find(fleet.id)
121
+ from_db.transports.size.should == 3
122
+ from_db.transports[0].license_plate.should == "ABC1223"
123
+ from_db.transports[0].model.should == "Honda Civic"
124
+ from_db.transports[0].year.should == 2003
125
+ from_db.transports[1].license_plate.should == "XYZ9090"
126
+ from_db.transports[1].max_passengers.should == 51
127
+ from_db.transports[2].license_plate.should == "HDD3030"
128
+ from_db.transports[2].icu.should == true
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,106 @@
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class ManyEmbeddedProxyTest < Test::Unit::TestCase
5
+ def setup
6
+ clear_all_collections
7
+ end
8
+
9
+ should "default reader to empty array" do
10
+ Project.new.addresses.should == []
11
+ end
12
+
13
+ should "allow adding to association like it was an array" do
14
+ project = Project.new
15
+ project.addresses << Address.new
16
+ project.addresses.push Address.new
17
+ project.addresses.size.should == 2
18
+ end
19
+
20
+ should "be embedded in document on save" do
21
+ sb = Address.new(:city => 'South Bend', :state => 'IN')
22
+ chi = Address.new(:city => 'Chicago', :state => 'IL')
23
+ project = Project.new
24
+ project.addresses << sb
25
+ project.addresses << chi
26
+ project.save
27
+
28
+ from_db = Project.find(project.id)
29
+ from_db.addresses.size.should == 2
30
+ from_db.addresses[0].should == sb
31
+ from_db.addresses[1].should == chi
32
+ end
33
+
34
+ should "allow embedding arbitrarily deep" do
35
+ @document = Class.new do
36
+ include MongoMapper::Document
37
+ key :person, Person
38
+ end
39
+ @document.collection.clear
40
+
41
+ meg = Person.new(:name => "Meg")
42
+ meg.child = Person.new(:name => "Steve")
43
+ meg.child.child = Person.new(:name => "Linda")
44
+
45
+ doc = @document.new(:person => meg)
46
+ doc.save
47
+
48
+ from_db = @document.find(doc.id)
49
+ from_db.person.name.should == 'Meg'
50
+ from_db.person.child.name.should == 'Steve'
51
+ from_db.person.child.child.name.should == 'Linda'
52
+ end
53
+
54
+ should "allow assignment of 'many' embedded documents using a hash" do
55
+ person_attributes = {
56
+ "name" => "Mr. Pet Lover",
57
+ "pets" => [
58
+ {"name" => "Jimmy", "species" => "Cocker Spainel"},
59
+ {"name" => "Sasha", "species" => "Siberian Husky"},
60
+ ]
61
+ }
62
+
63
+ pet_lover = RealPerson.new(person_attributes)
64
+ pet_lover.name.should == "Mr. Pet Lover"
65
+ pet_lover.pets[0].name.should == "Jimmy"
66
+ pet_lover.pets[0].species.should == "Cocker Spainel"
67
+ pet_lover.pets[1].name.should == "Sasha"
68
+ pet_lover.pets[1].species.should == "Siberian Husky"
69
+ pet_lover.save.should be_true
70
+
71
+ from_db = RealPerson.find(pet_lover.id)
72
+ from_db.name.should == "Mr. Pet Lover"
73
+ from_db.pets[0].name.should == "Jimmy"
74
+ from_db.pets[0].species.should == "Cocker Spainel"
75
+ from_db.pets[1].name.should == "Sasha"
76
+ from_db.pets[1].species.should == "Siberian Husky"
77
+ end
78
+
79
+ should "allow saving embedded documents in 'many' embedded documents" do
80
+ @document = Class.new do
81
+ include MongoMapper::Document
82
+ many :people
83
+ end
84
+ @document.collection.clear
85
+
86
+ meg = Person.new(:name => "Meg")
87
+ sparky = Pet.new(:name => "Sparky", :species => "Dog")
88
+ koda = Pet.new(:name => "Koda", :species => "Dog")
89
+
90
+ doc = @document.new
91
+
92
+ meg.pets << sparky
93
+ meg.pets << koda
94
+
95
+ doc.people << meg
96
+ doc.save
97
+
98
+ from_db = @document.find(doc.id)
99
+ from_db.people.first.name.should == "Meg"
100
+ from_db.people.first.pets.should_not == []
101
+ from_db.people.first.pets.first.name.should == "Sparky"
102
+ from_db.people.first.pets.first.species.should == "Dog"
103
+ from_db.people.first.pets[1].name.should == "Koda"
104
+ from_db.people.first.pets[1].species.should == "Dog"
105
+ end
106
+ end
@@ -0,0 +1,259 @@
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class ManyPolymorphicProxyTest < Test::Unit::TestCase
5
+ def setup
6
+ clear_all_collections
7
+ end
8
+
9
+ should "default reader to empty array" do
10
+ Room.new.messages.should == []
11
+ end
12
+
13
+ should "add type key to polymorphic class base" do
14
+ Message.keys.keys.should include('_type')
15
+ end
16
+
17
+ should "allow adding to assiciation like it was an array" do
18
+ room = Room.new
19
+ room.messages << Enter.new
20
+ room.messages.push Exit.new
21
+ room.messages.concat Exit.new
22
+ room.messages.size.should == 3
23
+ end
24
+
25
+ should "be able to replace the association" do
26
+ room = Room.create(:name => 'Lounge')
27
+
28
+ lambda {
29
+ room.messages = [
30
+ Enter.new(:body => 'John entered room'),
31
+ Chat.new(:body => 'Heyyyoooo!'),
32
+ Exit.new(:body => 'John exited room')
33
+ ]
34
+ }.should change { Message.count }.by(3)
35
+
36
+ from_db = Room.find(room.id)
37
+ from_db.messages.size.should == 3
38
+ from_db.messages[0].body.should == 'John entered room'
39
+ from_db.messages[1].body.should == 'Heyyyoooo!'
40
+ from_db.messages[2].body.should == 'John exited room'
41
+ end
42
+
43
+ should "correctly store type when using <<, push and concat" do
44
+ room = Room.new
45
+ room.messages << Enter.new(:body => 'John entered the room')
46
+ room.messages.push Exit.new(:body => 'John entered the room')
47
+ room.messages.concat Chat.new(:body => 'Holla!')
48
+
49
+ from_db = Room.find(room.id)
50
+ from_db.messages[0]._type.should == 'Enter'
51
+ from_db.messages[1]._type.should == 'Exit'
52
+ from_db.messages[2]._type.should == 'Chat'
53
+ end
54
+
55
+ context "build" do
56
+ should "assign foreign key" do
57
+ room = Room.create
58
+ message = room.messages.build
59
+ message.room_id.should == room.id
60
+ end
61
+
62
+ should "assign _type" do
63
+ room = Room.create
64
+ message = room.messages.build
65
+ message._type.should == 'Message'
66
+ end
67
+
68
+ should "allow assigning attributes" do
69
+ room = Room.create
70
+ message = room.messages.build(:body => 'Foo!')
71
+ message.body.should == 'Foo!'
72
+ end
73
+ end
74
+
75
+ context "create" do
76
+ should "assign foreign key" do
77
+ room = Room.create
78
+ message = room.messages.create
79
+ message.room_id.should == room.id
80
+ end
81
+
82
+ should "assign _type" do
83
+ room = Room.create
84
+ message = room.messages.create
85
+ message._type.should == 'Message'
86
+ end
87
+
88
+ should "save record" do
89
+ room = Room.create
90
+ lambda {
91
+ room.messages.create
92
+ }.should change { Message.count }
93
+ end
94
+
95
+ should "allow passing attributes" do
96
+ room = Room.create
97
+ message = room.messages.create(:body => 'Foo!')
98
+ message.body.should == 'Foo!'
99
+ end
100
+ end
101
+
102
+ context "count" do
103
+ should "work scoped to association" do
104
+ room = Room.create
105
+ 3.times { room.messages.create }
106
+
107
+ other_room = Room.create
108
+ 2.times { other_room.messages.create }
109
+
110
+ room.messages.count.should == 3
111
+ other_room.messages.count.should == 2
112
+ end
113
+
114
+ should "work with conditions" do
115
+ room = Room.create
116
+ room.messages.create(:body => 'Foo')
117
+ room.messages.create(:body => 'Other 1')
118
+ room.messages.create(:body => 'Other 2')
119
+
120
+ room.messages.count(:body => 'Foo').should == 1
121
+ end
122
+ end
123
+
124
+ context "Finding scoped to association" do
125
+ setup do
126
+ @lounge = Room.create(:name => 'Lounge')
127
+ @lm1 = Message.create(:body => 'Loungin!')
128
+ @lm2 = Message.create(:body => 'I love loungin!')
129
+ @lounge.messages = [@lm1, @lm2]
130
+ @lounge.save
131
+
132
+ @hall = Room.create(:name => 'Hall')
133
+ @hm1 = Message.create(:body => 'Do not fall in the hall')
134
+ @hm2 = Message.create(:body => 'Hall the king!')
135
+ @hm3 = Message.create(:body => 'Loungin!')
136
+ @hall.messages = [@hm1, @hm2, @hm3]
137
+ @hall.save
138
+ end
139
+
140
+ context "with :all" do
141
+ should "work" do
142
+ @lounge.messages.find(:all).should == [@lm1, @lm2]
143
+ end
144
+
145
+ should "work with conditions" do
146
+ messages = @lounge.messages.find(:all, :conditions => {:body => 'Loungin!'})
147
+ messages.should == [@lm1]
148
+ end
149
+
150
+ should "work with order" do
151
+ messages = @lounge.messages.find(:all, :order => '$natural desc')
152
+ messages.should == [@lm2, @lm1]
153
+ end
154
+ end
155
+
156
+ context "with #all" do
157
+ should "work" do
158
+ @lounge.messages.all.should == [@lm1, @lm2]
159
+ end
160
+
161
+ should "work with conditions" do
162
+ messages = @lounge.messages.all(:conditions => {'body' => 'Loungin!'})
163
+ messages.should == [@lm1]
164
+ end
165
+
166
+ should "work with order" do
167
+ messages = @lounge.messages.all(:order => '$natural desc')
168
+ messages.should == [@lm2, @lm1]
169
+ end
170
+ end
171
+
172
+ context "with :first" do
173
+ should "work" do
174
+ @lounge.messages.find(:first).should == @lm1
175
+ end
176
+
177
+ should "work with conditions" do
178
+ message = @lounge.messages.find(:first, :conditions => {:body => 'I love loungin!'})
179
+ message.should == @lm2
180
+ end
181
+ end
182
+
183
+ context "with #first" do
184
+ should "work" do
185
+ @lounge.messages.first.should == @lm1
186
+ end
187
+
188
+ should "work with conditions" do
189
+ message = @lounge.messages.first(:conditions => {:body => 'I love loungin!'})
190
+ message.should == @lm2
191
+ end
192
+ end
193
+
194
+ context "with :last" do
195
+ should "work" do
196
+ @lounge.messages.find(:last).should == @lm2
197
+ end
198
+
199
+ should "work with conditions" do
200
+ message = @lounge.messages.find(:last, :conditions => {:body => 'Loungin!'})
201
+ message.should == @lm1
202
+ end
203
+ end
204
+
205
+ context "with #last" do
206
+ should "work" do
207
+ @lounge.messages.last.should == @lm2
208
+ end
209
+
210
+ should "work with conditions" do
211
+ message = @lounge.messages.last(:conditions => {:body => 'Loungin!'})
212
+ message.should == @lm1
213
+ end
214
+ end
215
+
216
+ context "with one id" do
217
+ should "work for id in association" do
218
+ @lounge.messages.find(@lm2.id).should == @lm2
219
+ end
220
+
221
+ should "not work for id not in association" do
222
+ lambda {
223
+ @lounge.messages.find(@hm2.id)
224
+ }.should raise_error(MongoMapper::DocumentNotFound)
225
+ end
226
+ end
227
+
228
+ context "with multiple ids" do
229
+ should "work for ids in association" do
230
+ messages = @lounge.messages.find(@lm1.id, @lm2.id)
231
+ messages.should == [@lm1, @lm2]
232
+ end
233
+
234
+ should "not work for ids not in association" do
235
+ lambda {
236
+ @lounge.messages.find(@lm1.id, @lm2.id, @hm2.id)
237
+ }.should raise_error(MongoMapper::DocumentNotFound)
238
+ end
239
+ end
240
+
241
+ context "with #paginate" do
242
+ setup do
243
+ @messages = @hall.messages.paginate(:per_page => 2, :page => 1, :order => '$natural asc')
244
+ end
245
+
246
+ should "return total pages" do
247
+ @messages.total_pages.should == 2
248
+ end
249
+
250
+ should "return total entries" do
251
+ @messages.total_entries.should == 3
252
+ end
253
+
254
+ should "return the subject" do
255
+ @messages.should == [@hm1, @hm2]
256
+ end
257
+ end
258
+ end
259
+ end