mongo_mapper 0.15.0 → 0.15.1
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.
- checksums.yaml +4 -4
- data/README.md +5 -8
- data/lib/mongo_mapper.rb +2 -0
- data/lib/mongo_mapper/plugins/accessible.rb +1 -1
- data/lib/mongo_mapper/plugins/associations/base.rb +10 -2
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +36 -6
- data/lib/mongo_mapper/plugins/associations/in_foreign_array_proxy.rb +136 -0
- data/lib/mongo_mapper/plugins/associations/many_association.rb +4 -2
- data/lib/mongo_mapper/plugins/associations/proxy.rb +5 -1
- data/lib/mongo_mapper/plugins/associations/single_association.rb +5 -4
- data/lib/mongo_mapper/plugins/identity_map.rb +3 -1
- data/lib/mongo_mapper/plugins/keys.rb +8 -0
- data/lib/mongo_mapper/plugins/keys/key.rb +13 -8
- data/lib/mongo_mapper/plugins/modifiers.rb +12 -4
- data/lib/mongo_mapper/plugins/querying/decorated_plucky_query.rb +4 -3
- data/lib/mongo_mapper/plugins/strong_parameters.rb +26 -0
- data/lib/mongo_mapper/railtie.rb +1 -0
- data/lib/mongo_mapper/version.rb +1 -1
- data/spec/examples.txt +1655 -1581
- data/spec/functional/accessible_spec.rb +6 -0
- data/spec/functional/associations/belongs_to_proxy_spec.rb +18 -1
- data/spec/functional/associations/in_array_proxy_spec.rb +135 -0
- data/spec/functional/associations/in_foreign_array_proxy_spec.rb +321 -0
- data/spec/functional/document_spec.rb +0 -3
- data/spec/functional/identity_map_spec.rb +2 -2
- data/spec/functional/keys_spec.rb +29 -11
- data/spec/functional/modifiers_spec.rb +14 -0
- data/spec/functional/querying_spec.rb +22 -0
- data/spec/functional/strong_parameters_spec.rb +49 -0
- data/spec/unit/associations/proxy_spec.rb +0 -4
- data/spec/unit/keys_spec.rb +10 -1
- data/spec/unit/validations_spec.rb +18 -18
- metadata +6 -2
@@ -91,6 +91,12 @@ describe "Accessible" do
|
|
91
91
|
@doc.admin.should be_falsey
|
92
92
|
end
|
93
93
|
|
94
|
+
it "should ignore inaccessible attribute on #assign_attributes" do
|
95
|
+
@doc.assign_attributes({:name => 'Ren Hoek', :admin => true})
|
96
|
+
@doc.name.should == 'Ren Hoek'
|
97
|
+
@doc.admin.should be_falsey
|
98
|
+
end
|
99
|
+
|
94
100
|
it "should be indifferent to whether the accessible keys are strings or symbols" do
|
95
101
|
@doc.update_attributes!("name" => 'Stimpson J. Cat', "admin" => true)
|
96
102
|
@doc.name.should == 'Stimpson J. Cat'
|
@@ -51,7 +51,7 @@ describe "BelongsToProxy" do
|
|
51
51
|
it "should not reload the association when replacing" do
|
52
52
|
post = @post_class.new(:name => 'mongomapper')
|
53
53
|
comment = @comment_class.new(:name => 'Foo!', :post => post)
|
54
|
-
comment.post.
|
54
|
+
comment.post.object_id.should == post.object_id
|
55
55
|
end
|
56
56
|
|
57
57
|
it "should properly assign the associated object when assigning the association with create" do
|
@@ -252,4 +252,21 @@ describe "BelongsToProxy" do
|
|
252
252
|
post.reload.title.should == 'Hello, world!'
|
253
253
|
end
|
254
254
|
end
|
255
|
+
|
256
|
+
context "regression with reassignment" do
|
257
|
+
it "should not infinite regress (shouldn't raise SystemStackError) when assigned to twice (when the proxy isn't around)" do
|
258
|
+
post = @post_class.create!
|
259
|
+
comment = @comment_class.create!(post: post)
|
260
|
+
|
261
|
+
comment = @comment_class.find(comment.id)
|
262
|
+
|
263
|
+
post = comment.post
|
264
|
+
|
265
|
+
comment.post = post
|
266
|
+
|
267
|
+
lambda do
|
268
|
+
comment.post = post
|
269
|
+
end.should_not raise_error
|
270
|
+
end
|
271
|
+
end
|
255
272
|
end
|
@@ -346,4 +346,139 @@ describe "InArrayProxy" do
|
|
346
346
|
end
|
347
347
|
end
|
348
348
|
end
|
349
|
+
|
350
|
+
describe "ordering" do
|
351
|
+
before do
|
352
|
+
@user_class = Doc("User") do
|
353
|
+
key :list_ids, Array
|
354
|
+
end
|
355
|
+
|
356
|
+
@list_class = Doc("List") do
|
357
|
+
key :name, String, :required => true
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
def create_list_items
|
362
|
+
@user = @user_class.create!
|
363
|
+
@list1 = @list_class.create!(:name => "one")
|
364
|
+
@list2 = @list_class.create!(:name => "two")
|
365
|
+
@list3 = @list_class.create!(:name => "three")
|
366
|
+
|
367
|
+
@user.lists << [@list3, @list2, @list1]
|
368
|
+
@user.save!
|
369
|
+
|
370
|
+
@user.reload
|
371
|
+
end
|
372
|
+
|
373
|
+
shared_examples_for "ordering is on" do
|
374
|
+
it "should have the items ordered according to order of the ids" do
|
375
|
+
@user.lists.should == [@list3, @list2, @list1]
|
376
|
+
end
|
377
|
+
|
378
|
+
it "should have the right item for #first" do
|
379
|
+
@user.lists.first.should == @list3
|
380
|
+
end
|
381
|
+
|
382
|
+
it "should have the right item for #last" do
|
383
|
+
@user.lists.last.should == @list1
|
384
|
+
end
|
385
|
+
|
386
|
+
it "does not work for pagination (but probably should)" do
|
387
|
+
@user.lists.paginate(:per_page => 100).should == [@list1, @list2, @list3]
|
388
|
+
end
|
389
|
+
|
390
|
+
it "should work with find" do
|
391
|
+
@user.lists.find(@list2.id, @list1.id).should == [@list2, @list1]
|
392
|
+
@user.lists.find(@list1.id, @list2.id).should == [@list2, @list1]
|
393
|
+
@user.lists.find(@list1.id).should == @list1
|
394
|
+
end
|
395
|
+
|
396
|
+
it "should work with find!" do
|
397
|
+
@user.lists.find!(@list2.id, @list1.id).should == [@list2, @list1]
|
398
|
+
@user.lists.find!(@list1.id, @list2.id).should == [@list2, @list1]
|
399
|
+
end
|
400
|
+
|
401
|
+
it "should only load one object with first (and no params given)" do
|
402
|
+
@list_class.should_receive(:allocate).once.and_return @list3
|
403
|
+
@user.lists.first
|
404
|
+
end
|
405
|
+
|
406
|
+
it "should only load one object with first (and params given)" do
|
407
|
+
@list_class.should_receive(:allocate).once.and_return @list3
|
408
|
+
@user.lists.first(:name => /^t/)
|
409
|
+
end
|
410
|
+
|
411
|
+
it "should only load one object with last (and no params given)" do
|
412
|
+
@list_class.should_receive(:allocate).once.and_return @list1
|
413
|
+
@user.lists.last
|
414
|
+
end
|
415
|
+
|
416
|
+
it "should only load one object with last (and params given)" do
|
417
|
+
@list_class.should_receive(:allocate).once.and_return @list3
|
418
|
+
@user.lists.last(:name => /^t/)
|
419
|
+
end
|
420
|
+
|
421
|
+
it "should return nil if first with a query matches no objects" do
|
422
|
+
@user.lists.first(:name => "non-existent").should be_nil
|
423
|
+
end
|
424
|
+
|
425
|
+
it "should return nil if last with a query matches no objects" do
|
426
|
+
@user.lists.last(:name => "non-existent").should be_nil
|
427
|
+
end
|
428
|
+
|
429
|
+
it "should work with extra query params to first and last" do
|
430
|
+
@user.lists.first(:name => /^t/).should == @list3
|
431
|
+
@user.lists.first(:name => /^o/).should == @list1
|
432
|
+
|
433
|
+
@user.lists.last(:name => /^t/).should == @list2
|
434
|
+
@user.lists.last(:name => /^o/).should == @list1
|
435
|
+
end
|
436
|
+
end
|
437
|
+
|
438
|
+
shared_examples_for "ordering is off" do
|
439
|
+
it "should include all items" do
|
440
|
+
@user.lists.length == 3
|
441
|
+
@user.lists.should include(@list1)
|
442
|
+
@user.lists.should include(@list2)
|
443
|
+
@user.lists.should include(@list3)
|
444
|
+
end
|
445
|
+
|
446
|
+
it "should return the items in the natural order" do
|
447
|
+
@user.lists.should == [@list1, @list2, @list3]
|
448
|
+
end
|
449
|
+
|
450
|
+
it "should work with find" do
|
451
|
+
@user.lists.find(@list2.id, @list1.id).should == [@list1, @list2]
|
452
|
+
@user.lists.find(@list1.id, @list2.id).should == [@list1, @list2]
|
453
|
+
@user.lists.find(@list1.id).should == @list1
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
describe "without a param" do
|
458
|
+
before do
|
459
|
+
@user_class.many :lists, :in => :list_ids, :class => @list_class
|
460
|
+
create_list_items
|
461
|
+
end
|
462
|
+
|
463
|
+
it_behaves_like "ordering is off"
|
464
|
+
end
|
465
|
+
|
466
|
+
describe "with ordering off" do
|
467
|
+
before do
|
468
|
+
@user_class.many :lists, :in => :list_ids, :class => @list_class, :ordered => false
|
469
|
+
create_list_items
|
470
|
+
end
|
471
|
+
|
472
|
+
it_behaves_like "ordering is off"
|
473
|
+
end
|
474
|
+
|
475
|
+
describe "with ordering on" do
|
476
|
+
before do
|
477
|
+
@user_class.many :lists, :in => :list_ids, :class => @list_class, :ordered => true
|
478
|
+
create_list_items
|
479
|
+
end
|
480
|
+
|
481
|
+
it_behaves_like "ordering is on"
|
482
|
+
end
|
483
|
+
end
|
349
484
|
end
|
@@ -0,0 +1,321 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "InForeignArrayProxyTest" do
|
4
|
+
context "description" do
|
5
|
+
before do
|
6
|
+
class ::List
|
7
|
+
include MongoMapper::Document
|
8
|
+
key :name, String, :required => true
|
9
|
+
key :user_ids, Array
|
10
|
+
many :users, :in => :user_ids
|
11
|
+
end
|
12
|
+
|
13
|
+
class ::User
|
14
|
+
include MongoMapper::Document
|
15
|
+
key :name, String, :required => true
|
16
|
+
many :lists, :from => :user_ids, :as => :user
|
17
|
+
end
|
18
|
+
User.collection.drop
|
19
|
+
List.collection.drop
|
20
|
+
end
|
21
|
+
|
22
|
+
after do
|
23
|
+
Object.send :remove_const, 'List' if defined?(::List)
|
24
|
+
Object.send :remove_const, 'User' if defined?(::User)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should default reader to empty array" do
|
28
|
+
User.new.lists.should == []
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should allow adding to association like it was an array" do
|
32
|
+
user = User.new(:name => 'John')
|
33
|
+
user.lists << List.new(:name => 'Foo1!')
|
34
|
+
user.lists.push List.new(:name => 'Foo2!')
|
35
|
+
user.lists.concat List.new(:name => 'Foo3!')
|
36
|
+
user.lists.size.should == 3
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should ignore adding duplicate ids" do
|
40
|
+
user = User.create(:name => 'John')
|
41
|
+
list = List.create(:name => 'Foo')
|
42
|
+
user.lists << list
|
43
|
+
user.lists << list
|
44
|
+
user.lists << list
|
45
|
+
|
46
|
+
list.reload.user_ids.should == [user.id]
|
47
|
+
user.lists.count.should == 1
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should be able to replace the association" do
|
51
|
+
user = User.new(:name => 'John')
|
52
|
+
list = List.new(:name => 'Foo')
|
53
|
+
user.lists = [list]
|
54
|
+
user.save.should == true
|
55
|
+
|
56
|
+
user.reload
|
57
|
+
list.reload
|
58
|
+
list.user_ids.should == [user.id]
|
59
|
+
user.lists.size.should == 1
|
60
|
+
user.lists[0].name.should == 'Foo'
|
61
|
+
end
|
62
|
+
|
63
|
+
context "create" do
|
64
|
+
before do
|
65
|
+
@user = User.create(:name => 'John')
|
66
|
+
@list = @user.lists.create(:name => 'Foo!')
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should add id to key" do
|
70
|
+
@list.user_ids.should include(@user.id)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should persist id addition to key in database" do
|
74
|
+
@list.reload
|
75
|
+
@list.user_ids.should include(@user.id)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should add doc to association" do
|
79
|
+
@user.lists.should include(@list)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should save doc" do
|
83
|
+
@list.should_not be_new
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should reset cache" do
|
87
|
+
@user.lists.size.should == 1
|
88
|
+
@user.lists.create(:name => 'Moo!')
|
89
|
+
@user.lists.size.should == 2
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "create!" do
|
94
|
+
before do
|
95
|
+
@user = User.create(:name => 'John')
|
96
|
+
@list = @user.lists.create!(:name => 'Foo!')
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should add id to key" do
|
100
|
+
@list.user_ids.should include(@user.id)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should persist id addition to key in database" do
|
104
|
+
@list.reload
|
105
|
+
@list.user_ids.should include(@user.id)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should add doc to association" do
|
109
|
+
@user.lists.should include(@list)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should save doc" do
|
113
|
+
@list.should_not be_new
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should raise exception if invalid" do
|
117
|
+
lambda do
|
118
|
+
@user.lists.create!
|
119
|
+
end.should raise_error(MongoMapper::DocumentNotValid)
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should reset cache" do
|
123
|
+
@user.lists.size.should == 1
|
124
|
+
@user.lists.create!(:name => 'Moo!')
|
125
|
+
@user.lists.size.should == 2
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context "Finding scoped to association" do
|
130
|
+
before do
|
131
|
+
@user = User.create(:name => 'John')
|
132
|
+
@user2 = User.create(:name => 'Brandon')
|
133
|
+
@list1 = @user.lists.create!(:name => 'Foo 1', :position => 1)
|
134
|
+
@list2 = @user.lists.create!(:name => 'Foo 2', :position => 2)
|
135
|
+
@list3 = @user2.lists.create!(:name => 'Foo 3', :position => 1)
|
136
|
+
end
|
137
|
+
|
138
|
+
context "all" do
|
139
|
+
it "should work" do
|
140
|
+
@user.lists.all(:order => :position.asc).should == [@list1, @list2]
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should work with conditions" do
|
144
|
+
@user.lists.all(:name => 'Foo 1').should == [@list1]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context "first" do
|
149
|
+
it "should work" do
|
150
|
+
@user.lists.first(:order => 'position').should == @list1
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should work with conditions" do
|
154
|
+
@user.lists.first(:position => 2).should == @list2
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context "last" do
|
159
|
+
it "should work" do
|
160
|
+
@user.lists.last(:order => 'position').should == @list2
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should work with conditions" do
|
164
|
+
@user.lists.last(:position => 2, :order => 'position').should == @list2
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context "with one id" do
|
169
|
+
it "should work for id in association" do
|
170
|
+
@user.lists.find(@list1.id).should == @list1
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should work with string ids" do
|
174
|
+
@user.lists.find(@list1.id.to_s).should == @list1
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should not work for id not in association" do
|
178
|
+
@user.lists.find(@list3.id).should be_nil
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should raise error when using ! and not found" do
|
182
|
+
lambda do
|
183
|
+
@user.lists.find!(@list3.id)
|
184
|
+
end.should raise_error(MongoMapper::DocumentNotFound)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context "with multiple ids" do
|
189
|
+
it "should work for ids in association" do
|
190
|
+
@user.lists.find(@list1.id, @list2.id).should == [@list1, @list2]
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should not work for ids not in association" do
|
194
|
+
@user.lists.find(@list1.id, @list2.id, @list3.id).should == [@list1, @list2]
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context "with #paginate" do
|
199
|
+
before do
|
200
|
+
@lists = @user.lists.paginate(:per_page => 1, :page => 1, :order => 'position')
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should return total pages" do
|
204
|
+
@lists.total_pages.should == 2
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should return total entries" do
|
208
|
+
@lists.total_entries.should == 2
|
209
|
+
end
|
210
|
+
|
211
|
+
it "should return the subject" do
|
212
|
+
@lists.collect(&:name).should == ['Foo 1']
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context "dynamic finders" do
|
217
|
+
it "should work with single key" do
|
218
|
+
@user.lists.find_by_name('Foo 1').should == @list1
|
219
|
+
@user.lists.find_by_name!('Foo 1').should == @list1
|
220
|
+
@user.lists.find_by_name('Foo 3').should be_nil
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should work with multiple keys" do
|
224
|
+
@user.lists.find_by_name_and_position('Foo 1', 1).should == @list1
|
225
|
+
@user.lists.find_by_name_and_position!('Foo 1', 1).should == @list1
|
226
|
+
@user.lists.find_by_name_and_position('Foo 3', 1).should be_nil
|
227
|
+
end
|
228
|
+
|
229
|
+
it "should raise error when using ! and not found" do
|
230
|
+
lambda do
|
231
|
+
@user.lists.find_by_name!('Foo 3')
|
232
|
+
end.should raise_error(MongoMapper::DocumentNotFound)
|
233
|
+
end
|
234
|
+
|
235
|
+
context "find_or_create_by" do
|
236
|
+
it "should not create document if found" do
|
237
|
+
lambda {
|
238
|
+
list = @user.lists.find_or_create_by_name('Foo 1')
|
239
|
+
list.should == @list1
|
240
|
+
}.should_not change { List.count }
|
241
|
+
end
|
242
|
+
|
243
|
+
it "should create document if not found" do
|
244
|
+
lambda {
|
245
|
+
list = @user.lists.find_or_create_by_name('Home')
|
246
|
+
@user.lists.should include(list)
|
247
|
+
}.should change { List.count }
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
context "count" do
|
254
|
+
before do
|
255
|
+
@user = User.create(:name => 'John')
|
256
|
+
@user2 = User.create(:name => 'Brandon')
|
257
|
+
@list1 = @user.lists.create!(:name => 'Foo 1')
|
258
|
+
@list2 = @user.lists.create!(:name => 'Foo 2')
|
259
|
+
@list3 = @user2.lists.create!(:name => 'Foo 3')
|
260
|
+
end
|
261
|
+
|
262
|
+
it "should return number of ids" do
|
263
|
+
@user.lists.count.should == 2
|
264
|
+
@user2.lists.count.should == 1
|
265
|
+
end
|
266
|
+
|
267
|
+
it "should return correct count when given criteria" do
|
268
|
+
@user.lists.count(:name => 'Foo 1').should == 1
|
269
|
+
@user2.lists.count(:name => 'Foo 1').should == 0
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
context "Removing documents" do
|
274
|
+
before do
|
275
|
+
@user = User.create(:name => 'John')
|
276
|
+
@user2 = User.create(:name => 'Brandon')
|
277
|
+
@list1 = @user.lists.create!(:name => 'Foo 1', :position => 1)
|
278
|
+
@list2 = @user.lists.create!(:name => 'Foo 2', :position => 2)
|
279
|
+
@list3 = @user2.lists.create!(:name => 'Foo 3', :position => 1)
|
280
|
+
end
|
281
|
+
|
282
|
+
context "destroy_all" do
|
283
|
+
it "should work" do
|
284
|
+
@user.lists.count.should == 2
|
285
|
+
@user.lists.destroy_all
|
286
|
+
@user.lists.count.should == 0
|
287
|
+
end
|
288
|
+
|
289
|
+
it "should work with conditions" do
|
290
|
+
@user.lists.count.should == 2
|
291
|
+
@user.lists.destroy_all(:name => 'Foo 1')
|
292
|
+
@user.lists.count.should == 1
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
context "delete_all" do
|
297
|
+
it "should work" do
|
298
|
+
@user.lists.count.should == 2
|
299
|
+
@user.lists.delete_all
|
300
|
+
@user.lists.count.should == 0
|
301
|
+
end
|
302
|
+
|
303
|
+
it "should work with conditions" do
|
304
|
+
@user.lists.count.should == 2
|
305
|
+
@user.lists.delete_all(:name => 'Foo 1')
|
306
|
+
@user.lists.count.should == 1
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
it "should work with nullify" do
|
311
|
+
@user.lists.count.should == 2
|
312
|
+
|
313
|
+
lambda {
|
314
|
+
@user.lists.nullify
|
315
|
+
}.should_not change { List.count }
|
316
|
+
|
317
|
+
@user.lists.count.should == 0
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|