drogus-mongo_mapper 0.6.10

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 (91) hide show
  1. data/.gitignore +10 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +29 -0
  4. data/Rakefile +55 -0
  5. data/VERSION +1 -0
  6. data/bin/mmconsole +60 -0
  7. data/lib/mongo_mapper.rb +131 -0
  8. data/lib/mongo_mapper/document.rb +417 -0
  9. data/lib/mongo_mapper/embedded_document.rb +55 -0
  10. data/lib/mongo_mapper/finder_options.rb +127 -0
  11. data/lib/mongo_mapper/plugins.rb +30 -0
  12. data/lib/mongo_mapper/plugins/associations.rb +104 -0
  13. data/lib/mongo_mapper/plugins/associations/base.rb +121 -0
  14. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +30 -0
  15. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +25 -0
  16. data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
  17. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +50 -0
  18. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +139 -0
  19. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  20. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +117 -0
  21. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
  22. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
  23. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
  24. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +68 -0
  25. data/lib/mongo_mapper/plugins/associations/proxy.rb +118 -0
  26. data/lib/mongo_mapper/plugins/callbacks.rb +134 -0
  27. data/lib/mongo_mapper/plugins/clone.rb +13 -0
  28. data/lib/mongo_mapper/plugins/descendants.rb +16 -0
  29. data/lib/mongo_mapper/plugins/dirty.rb +119 -0
  30. data/lib/mongo_mapper/plugins/equality.rb +23 -0
  31. data/lib/mongo_mapper/plugins/identity_map.rb +122 -0
  32. data/lib/mongo_mapper/plugins/inspect.rb +14 -0
  33. data/lib/mongo_mapper/plugins/keys.rb +324 -0
  34. data/lib/mongo_mapper/plugins/logger.rb +17 -0
  35. data/lib/mongo_mapper/plugins/pagination.rb +85 -0
  36. data/lib/mongo_mapper/plugins/protected.rb +45 -0
  37. data/lib/mongo_mapper/plugins/rails.rb +45 -0
  38. data/lib/mongo_mapper/plugins/serialization.rb +105 -0
  39. data/lib/mongo_mapper/plugins/validations.rb +57 -0
  40. data/lib/mongo_mapper/support.rb +217 -0
  41. data/lib/mongo_mapper/support/descendant_appends.rb +46 -0
  42. data/lib/mongo_mapper/support/find.rb +77 -0
  43. data/mongo_mapper.gemspec +195 -0
  44. data/performance/read_write.rb +52 -0
  45. data/specs.watchr +51 -0
  46. data/test/NOTE_ON_TESTING +1 -0
  47. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +63 -0
  48. data/test/functional/associations/test_belongs_to_proxy.rb +101 -0
  49. data/test/functional/associations/test_in_array_proxy.rb +309 -0
  50. data/test/functional/associations/test_many_documents_as_proxy.rb +229 -0
  51. data/test/functional/associations/test_many_documents_proxy.rb +431 -0
  52. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +176 -0
  53. data/test/functional/associations/test_many_embedded_proxy.rb +256 -0
  54. data/test/functional/associations/test_many_polymorphic_proxy.rb +302 -0
  55. data/test/functional/associations/test_one_proxy.rb +161 -0
  56. data/test/functional/test_associations.rb +44 -0
  57. data/test/functional/test_binary.rb +27 -0
  58. data/test/functional/test_callbacks.rb +81 -0
  59. data/test/functional/test_dirty.rb +163 -0
  60. data/test/functional/test_document.rb +1264 -0
  61. data/test/functional/test_embedded_document.rb +125 -0
  62. data/test/functional/test_identity_map.rb +508 -0
  63. data/test/functional/test_logger.rb +20 -0
  64. data/test/functional/test_modifiers.rb +252 -0
  65. data/test/functional/test_pagination.rb +93 -0
  66. data/test/functional/test_protected.rb +155 -0
  67. data/test/functional/test_string_id_compatibility.rb +67 -0
  68. data/test/functional/test_validations.rb +329 -0
  69. data/test/models.rb +232 -0
  70. data/test/support/custom_matchers.rb +55 -0
  71. data/test/support/timing.rb +16 -0
  72. data/test/test_helper.rb +60 -0
  73. data/test/unit/associations/test_base.rb +207 -0
  74. data/test/unit/associations/test_proxy.rb +105 -0
  75. data/test/unit/serializers/test_json_serializer.rb +189 -0
  76. data/test/unit/test_descendant_appends.rb +71 -0
  77. data/test/unit/test_document.rb +231 -0
  78. data/test/unit/test_dynamic_finder.rb +123 -0
  79. data/test/unit/test_embedded_document.rb +663 -0
  80. data/test/unit/test_finder_options.rb +329 -0
  81. data/test/unit/test_keys.rb +169 -0
  82. data/test/unit/test_mongo_mapper.rb +65 -0
  83. data/test/unit/test_pagination.rb +127 -0
  84. data/test/unit/test_plugins.rb +50 -0
  85. data/test/unit/test_rails.rb +123 -0
  86. data/test/unit/test_rails_compatibility.rb +52 -0
  87. data/test/unit/test_serialization.rb +51 -0
  88. data/test/unit/test_support.rb +354 -0
  89. data/test/unit/test_time_zones.rb +39 -0
  90. data/test/unit/test_validations.rb +544 -0
  91. metadata +290 -0
@@ -0,0 +1,256 @@
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class ManyEmbeddedProxyTest < Test::Unit::TestCase
5
+ def setup
6
+ @comment_class = EDoc do
7
+ key :name, String
8
+ key :body, String
9
+ end
10
+ @post_class = Doc do
11
+ key :title, String
12
+ end
13
+ @post_class.many :comments, :class => @comment_class
14
+
15
+ @pet_class = EDoc do
16
+ key :name, String
17
+ end
18
+ @pet_class.embedded_in :person
19
+ @person_class = EDoc do
20
+ key :name, String
21
+ end
22
+ @person_class.key :child, @person_class
23
+ @person_class.many :pets, :class => @pet_class
24
+
25
+ @owner_class = Doc do
26
+ key :name, String
27
+ end
28
+ @owner_class.many :pets, :class => @pet_class
29
+ end
30
+
31
+ should "default reader to empty array" do
32
+ @post_class.new.comments.should == []
33
+ end
34
+
35
+ should "allow adding to association like it was an array" do
36
+ post = @post_class.new
37
+ post.comments << @comment_class.new
38
+ post.comments.push @comment_class.new
39
+ post.comments.size.should == 2
40
+ end
41
+
42
+ should "be embedded in document on save" do
43
+ frank = @comment_class.new(:name => 'Frank', :body => 'Hi!')
44
+ bill = @comment_class.new(:name => 'Bill', :body => 'Hi!')
45
+ post = @post_class.new
46
+ post.comments << frank
47
+ post.comments << bill
48
+ post.save
49
+
50
+ post.reload
51
+ post.comments.size.should == 2
52
+ post.comments[0].should == frank
53
+ post.comments[0].new?.should == false
54
+ post.comments[1].should == bill
55
+ post.comments[1].new?.should == false
56
+ end
57
+
58
+ should "allow embedding arbitrarily deep" do
59
+ @klass = Doc()
60
+ @klass.key :person, @person_class
61
+
62
+ meg = @person_class.new(:name => 'Meg')
63
+ meg.child = @person_class.new(:name => 'Steve')
64
+ meg.child.child = @person_class.new(:name => 'Linda')
65
+
66
+ doc = @klass.new(:person => meg)
67
+ doc.save
68
+ doc.reload
69
+
70
+ doc.person.name.should == 'Meg'
71
+ doc.person.child.name.should == 'Steve'
72
+ doc.person.child.child.name.should == 'Linda'
73
+ end
74
+
75
+ should "allow assignment of many embedded documents using a hash" do
76
+ person_attributes = {
77
+ 'name' => 'Mr. Pet Lover',
78
+ 'pets' => [
79
+ {'name' => 'Jimmy', 'species' => 'Cocker Spainel'},
80
+ {'name' => 'Sasha', 'species' => 'Siberian Husky'},
81
+ ]
82
+ }
83
+
84
+ owner = @owner_class.new(person_attributes)
85
+ owner.name.should == 'Mr. Pet Lover'
86
+ owner.pets[0].name.should == 'Jimmy'
87
+ owner.pets[0].species.should == 'Cocker Spainel'
88
+ owner.pets[1].name.should == 'Sasha'
89
+ owner.pets[1].species.should == 'Siberian Husky'
90
+
91
+ owner.save.should be_true
92
+ owner.reload
93
+
94
+ owner.name.should == 'Mr. Pet Lover'
95
+ owner.pets[0].name.should == 'Jimmy'
96
+ owner.pets[0].species.should == 'Cocker Spainel'
97
+ owner.pets[1].name.should == 'Sasha'
98
+ owner.pets[1].species.should == 'Siberian Husky'
99
+ end
100
+
101
+ context "embedding many embedded documents" do
102
+ setup do
103
+ @klass = Doc()
104
+ @klass.many :people, :class => @person_class
105
+ end
106
+
107
+ should "persist all embedded documents" do
108
+ meg = @person_class.new(:name => 'Meg', :pets => [
109
+ @pet_class.new(:name => 'Sparky', :species => 'Dog'),
110
+ @pet_class.new(:name => 'Koda', :species => 'Dog')
111
+ ])
112
+
113
+ doc = @klass.new
114
+ doc.people << meg
115
+ doc.save
116
+ doc.reload
117
+
118
+ doc.people.first.name.should == 'Meg'
119
+ doc.people.first.pets.should_not == []
120
+ doc.people.first.pets.first.name.should == 'Sparky'
121
+ doc.people.first.pets.first.species.should == 'Dog'
122
+ doc.people.first.pets[1].name.should == 'Koda'
123
+ doc.people.first.pets[1].species.should == 'Dog'
124
+ end
125
+
126
+ should "create a reference to the root document for all embedded documents before save" do
127
+ doc = @klass.new
128
+ meg = @person_class.new(:name => 'Meg')
129
+ pet = @pet_class.new(:name => 'Sparky', :species => 'Dog')
130
+
131
+ doc.people << meg
132
+ meg.pets << pet
133
+
134
+ doc.people.first._root_document.should == doc
135
+ doc.people.first.pets.first._root_document.should == doc
136
+ end
137
+ should "create a reference to the owning document for all embedded documents before save" do
138
+ doc = @klass.new
139
+ meg = @person_class.new(:name => 'Meg')
140
+ pet = @pet_class.new(:name => 'Sparky', :species => 'Dog')
141
+
142
+ doc.people << meg
143
+ meg.pets << pet
144
+
145
+ doc.people.first._parent_document.should == doc
146
+ doc.people.first.pets.first._parent_document.should == doc.people.first
147
+ end
148
+
149
+ should "create a reference to the root document for all embedded documents" do
150
+ sparky = @pet_class.new(:name => 'Sparky', :species => 'Dog')
151
+ meg = @person_class.new(:name => 'Meg', :pets => [sparky])
152
+ doc = @klass.new
153
+ doc.people << meg
154
+ doc.save
155
+
156
+ doc.reload
157
+ doc.people.first._root_document.should == doc
158
+ doc.people.first.pets.first._root_document.should == doc
159
+ end
160
+ should "create a reference to the owning document for all embedded documents" do
161
+ doc = @klass.new
162
+ meg = @person_class.new(:name => 'Meg')
163
+ pet = @pet_class.new(:name => 'Sparky', :species => 'Dog')
164
+
165
+ doc.people << meg
166
+ meg.pets << pet
167
+ doc.save
168
+
169
+ doc.reload
170
+ doc.people.first._parent_document.should == doc
171
+ doc.people.first.pets.first._parent_document.should == doc.people.first
172
+ end
173
+
174
+ should "create embedded_in relationship for embedded docs" do
175
+ doc = @klass.new
176
+ meg = @person_class.new(:name => 'Meg')
177
+ pet = @pet_class.new(:name => 'Sparky', :species => 'Dog')
178
+
179
+ doc.people << meg
180
+ meg.pets << pet
181
+ doc.save
182
+
183
+ doc.reload
184
+ doc.people.first.pets.first.person.should == doc.people.first
185
+ end
186
+ end
187
+
188
+ should "allow finding by id" do
189
+ sparky = @pet_class.new(:name => 'Sparky', :species => 'Dog')
190
+ meg = @owner_class.create(:name => 'Meg', :pets => [sparky])
191
+
192
+ meg.pets.find(sparky._id).should == sparky # oid
193
+ meg.pets.find(sparky.id.to_s).should == sparky # string
194
+ end
195
+
196
+ context "count" do
197
+ should "default to 0" do
198
+ @owner_class.new.pets.count.should == 0
199
+ end
200
+
201
+ should "return correct count if any are embedded" do
202
+ owner = @owner_class.new(:name => 'Meg')
203
+ owner.pets = [@pet_class.new, @pet_class.new]
204
+ owner.pets.count.should == 2
205
+ owner.save
206
+ owner.reload
207
+ owner.pets.count.should == 2
208
+ end
209
+ end
210
+
211
+ context "extending the association" do
212
+ setup do
213
+ @address_class = EDoc do
214
+ key :address, String
215
+ key :city, String
216
+ key :state, String
217
+ key :zip, Integer
218
+ end
219
+
220
+ @project_class = Doc do
221
+ key :name, String
222
+ end
223
+ end
224
+
225
+ should "work using a block passed to many" do
226
+ @project_class.many :addresses, :class => @address_class do
227
+ def find_all_by_state(state)
228
+ find_all { |a| a.state == state }
229
+ end
230
+ end
231
+
232
+ addr1 = @address_class.new(:address => "Gate-3 Lankershim Blvd.", :city => "Universal City", :state => "CA", :zip => "91608")
233
+ addr2 = @address_class.new(:address => "3000 W. Alameda Ave.", :city => "Burbank", :state => "CA", :zip => "91523")
234
+ addr3 = @address_class.new(:address => "111 Some Ln", :city => "Nashville", :state => "TN", :zip => "37211")
235
+ project = @project_class.create(:name => "Some Project", :addresses => [addr1, addr2, addr3])
236
+
237
+ project.addresses.find_all_by_state("CA").should == [addr1, addr2]
238
+ end
239
+
240
+ should "work using many's :extend option" do
241
+ module FindByCity
242
+ def find_by_city(city)
243
+ find_all { |a| a.city == city }
244
+ end
245
+ end
246
+ @project_class.many :addresses, :class => @address_class, :extend => FindByCity
247
+
248
+ addr1 = @address_class.new(:address => "Gate-3 Lankershim Blvd.", :city => "Universal City", :state => "CA", :zip => "91608")
249
+ addr2 = @address_class.new(:address => "3000 W. Alameda Ave.", :city => "Burbank", :state => "CA", :zip => "91523")
250
+ addr3 = @address_class.new(:address => "111 Some Ln", :city => "Nashville", :state => "TN", :zip => "37211")
251
+ project = @project_class.create(:name => "Some Project", :addresses => [addr1, addr2, addr3])
252
+
253
+ project.addresses.find_by_city('Burbank').should == [addr2]
254
+ end
255
+ end
256
+ end
@@ -0,0 +1,302 @@
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class ManyPolymorphicProxyTest < Test::Unit::TestCase
5
+ def setup
6
+ Room.collection.remove
7
+ Message.collection.remove
8
+ end
9
+
10
+ should "default reader to empty array" do
11
+ Room.new.messages.should == []
12
+ end
13
+
14
+ should "add type key to polymorphic class base" do
15
+ Message.keys.keys.should include('_type')
16
+ end
17
+
18
+ should "allow adding to assiciation like it was an array" do
19
+ room = Room.new
20
+ room.messages << Enter.new
21
+ room.messages.push Exit.new
22
+ room.messages.concat Exit.new
23
+ room.messages.size.should == 3
24
+ end
25
+
26
+ should "be able to replace the association" do
27
+ room = Room.create(:name => 'Lounge')
28
+
29
+ lambda {
30
+ room.messages = [
31
+ Enter.new(:body => 'John entered room', :position => 1),
32
+ Chat.new(:body => 'Heyyyoooo!', :position => 2),
33
+ Exit.new(:body => 'John exited room', :position => 3)
34
+ ]
35
+ }.should change { Message.count }.by(3)
36
+
37
+ room = room.reload
38
+ messages = room.messages.all :order => "position"
39
+ messages.size.should == 3
40
+ messages[0].body.should == 'John entered room'
41
+ messages[1].body.should == 'Heyyyoooo!'
42
+ messages[2].body.should == 'John exited room'
43
+ end
44
+
45
+ should "correctly store type when using <<, push and concat" do
46
+ room = Room.new
47
+ room.messages << Enter.new(:body => 'John entered the room', :position => 1)
48
+ room.messages.push Exit.new(:body => 'John entered the room', :position => 2)
49
+ room.messages.concat Chat.new(:body => 'Holla!' , :position => 3)
50
+
51
+ room = room.reload
52
+ messages = room.messages.all :order => "position"
53
+ messages[0]._type.should == 'Enter'
54
+ messages[1]._type.should == 'Exit'
55
+ messages[2]._type.should == 'Chat'
56
+ end
57
+
58
+ context "build" do
59
+ should "assign foreign key" do
60
+ room = Room.create
61
+ message = room.messages.build
62
+ message.room_id.should == room._id
63
+ end
64
+
65
+ should "assign _type" do
66
+ room = Room.create
67
+ message = room.messages.build
68
+ message._type.should == 'Message'
69
+ end
70
+
71
+ should "allow assigning attributes" do
72
+ room = Room.create
73
+ message = room.messages.build(:body => 'Foo!')
74
+ message.body.should == 'Foo!'
75
+ end
76
+ end
77
+
78
+ context "create" do
79
+ should "assign foreign key" do
80
+ room = Room.create
81
+ message = room.messages.create
82
+ message.room_id.should == room._id
83
+ end
84
+
85
+ should "assign _type" do
86
+ room = Room.create
87
+ message = room.messages.create
88
+ message._type.should == 'Message'
89
+ end
90
+
91
+ should "save record" do
92
+ room = Room.create
93
+ lambda {
94
+ room.messages.create
95
+ }.should change { Message.count }
96
+ end
97
+
98
+ should "allow passing attributes" do
99
+ room = Room.create
100
+ message = room.messages.create(:body => 'Foo!')
101
+ message.body.should == 'Foo!'
102
+ end
103
+ end
104
+
105
+ context "count" do
106
+ should "work scoped to association" do
107
+ room = Room.create
108
+ 3.times { room.messages.create }
109
+
110
+ other_room = Room.create
111
+ 2.times { other_room.messages.create }
112
+
113
+ room.messages.count.should == 3
114
+ other_room.messages.count.should == 2
115
+ end
116
+
117
+ should "work with conditions" do
118
+ room = Room.create
119
+ room.messages.create(:body => 'Foo')
120
+ room.messages.create(:body => 'Other 1')
121
+ room.messages.create(:body => 'Other 2')
122
+
123
+ room.messages.count(:body => 'Foo').should == 1
124
+ end
125
+ end
126
+
127
+ context "Finding scoped to association" do
128
+ setup do
129
+ @lounge = Room.create(:name => 'Lounge')
130
+ @lm1 = Message.create(:body => 'Loungin!', :position => 1)
131
+ @lm2 = Message.create(:body => 'I love loungin!', :position => 2)
132
+ @lounge.messages = [@lm1, @lm2]
133
+ @lounge.save
134
+
135
+ @hall = Room.create(:name => 'Hall')
136
+ @hm1 = Message.create(:body => 'Do not fall in the hall', :position => 1)
137
+ @hm3 = Message.create(:body => 'Loungin!', :position => 3)
138
+ @hm2 = Message.create(:body => 'Hall the king!', :position => 2)
139
+ @hall.messages = [@hm1, @hm2, @hm3]
140
+ @hall.save
141
+ end
142
+
143
+ context "dynamic finders" do
144
+ should "work with single key" do
145
+ @lounge.messages.find_by_position(1).should == @lm1
146
+ @hall.messages.find_by_position(2).should == @hm2
147
+ end
148
+
149
+ should "work with multiple keys" do
150
+ @lounge.messages.find_by_body_and_position('Loungin!', 1).should == @lm1
151
+ @lounge.messages.find_by_body_and_position('Loungin!', 2).should be_nil
152
+ end
153
+
154
+ should "raise error when using !" do
155
+ lambda {
156
+ @lounge.messages.find_by_position!(222)
157
+ }.should raise_error(MongoMapper::DocumentNotFound)
158
+ end
159
+
160
+ context "find_or_create_by" do
161
+ should "not create document if found" do
162
+ lambda {
163
+ message = @lounge.messages.find_or_create_by_body('Loungin!')
164
+ message.room.should == @lounge
165
+ message.should == @lm1
166
+ }.should_not change { Message.count }
167
+ end
168
+
169
+ should "create document if not found" do
170
+ lambda {
171
+ message = @lounge.messages.find_or_create_by_body('Yo dawg!')
172
+ message.room.should == @lounge
173
+ message._type.should == 'Message'
174
+ }.should change { Message.count }.by(1)
175
+ end
176
+ end
177
+ end
178
+
179
+ context "with #all" do
180
+ should "work" do
181
+ @lounge.messages.all(:order => "position").should == [@lm1, @lm2]
182
+ end
183
+
184
+ should "work with conditions" do
185
+ messages = @lounge.messages.all(:body => 'Loungin!', :order => "position")
186
+ messages.should == [@lm1]
187
+ end
188
+
189
+ should "work with order" do
190
+ messages = @lounge.messages.all(:order => 'position desc')
191
+ messages.should == [@lm2, @lm1]
192
+ end
193
+ end
194
+
195
+ context "with #first" do
196
+ should "work" do
197
+ @lounge.messages.first(:order => "position asc").should == @lm1
198
+ end
199
+
200
+ should "work with conditions" do
201
+ message = @lounge.messages.first(:body => 'I love loungin!', :order => "position asc")
202
+ message.should == @lm2
203
+ end
204
+ end
205
+
206
+ context "with #last" do
207
+ should "work" do
208
+ @lounge.messages.last(:order => "position asc").should == @lm2
209
+ end
210
+
211
+ should "work with conditions" do
212
+ message = @lounge.messages.last(:body => 'Loungin!', :order => "position asc")
213
+ message.should == @lm1
214
+ end
215
+ end
216
+
217
+ context "with one id" do
218
+ should "work for id in association" do
219
+ @lounge.messages.find(@lm2._id).should == @lm2
220
+ end
221
+
222
+ should "not work for id not in association" do
223
+ lambda {
224
+ @lounge.messages.find!(@hm2._id)
225
+ }.should raise_error(MongoMapper::DocumentNotFound)
226
+ end
227
+ end
228
+
229
+ context "with query options/criteria" do
230
+ should "work with order on association" do
231
+ @lounge.messages.should == [@lm1, @lm2]
232
+ end
233
+
234
+ should "allow overriding the order provided to the association" do
235
+ @lounge.messages.all(:order => 'position').should == [@lm1, @lm2]
236
+ end
237
+
238
+ should "allow using conditions on association" do
239
+ @hall.latest_messages.should == [@hm3, @hm2]
240
+ end
241
+ end
242
+
243
+ context "with multiple ids" do
244
+ should "work for ids in association" do
245
+ messages = @lounge.messages.find(@lm1._id, @lm2._id)
246
+ messages.should == [@lm1, @lm2]
247
+ end
248
+
249
+ should "not work for ids not in association" do
250
+ assert_raises(MongoMapper::DocumentNotFound) do
251
+ @lounge.messages.find!(@lm1._id, @lm2._id, @hm2._id)
252
+ end
253
+ end
254
+ end
255
+
256
+ context "with #paginate" do
257
+ setup do
258
+ @messages = @hall.messages.paginate(:per_page => 2, :page => 1, :order => 'position asc')
259
+ end
260
+
261
+ should "return total pages" do
262
+ @messages.total_pages.should == 2
263
+ end
264
+
265
+ should "return total entries" do
266
+ @messages.total_entries.should == 3
267
+ end
268
+
269
+ should "return the subject" do
270
+ @messages.should == [@hm1, @hm2]
271
+ end
272
+ end
273
+ end
274
+
275
+ context "extending the association" do
276
+ should "work using a block passed to many" do
277
+ room = Room.new(:name => "Amazing Room")
278
+ messages = room.messages = [
279
+ Enter.new(:body => 'John entered room', :position => 3),
280
+ Chat.new(:body => 'Heyyyoooo!', :position => 4),
281
+ Exit.new(:body => 'John exited room', :position => 5),
282
+ Enter.new(:body => 'Steve entered room', :position => 6),
283
+ Chat.new(:body => 'Anyone there?', :position => 7),
284
+ Exit.new(:body => 'Steve exited room', :position => 8)
285
+ ]
286
+ room.save
287
+ room.messages.older.should == messages[3..5]
288
+ end
289
+
290
+ should "work using many's :extend option" do
291
+
292
+ room = Room.new(:name => "Amazing Room")
293
+ accounts = room.accounts = [
294
+ Bot.new(:last_logged_in => 3.weeks.ago),
295
+ AccountUser.new(:last_logged_in => nil),
296
+ Bot.new(:last_logged_in => 1.week.ago)
297
+ ]
298
+ room.save
299
+ room.accounts.inactive.should == [accounts[1]]
300
+ end
301
+ end
302
+ end