mongo_mapper 0.5.0

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