mongo_mapper 0.5.0

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 (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