mongo_mapper 0.15.1 → 0.15.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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +6 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +3 -1
- data/lib/mongo_mapper/plugins/associations/proxy.rb +6 -2
- data/lib/mongo_mapper/plugins/dirty.rb +2 -2
- data/lib/mongo_mapper/plugins/embedded_document.rb +1 -1
- data/lib/mongo_mapper/plugins/keys.rb +3 -5
- data/lib/mongo_mapper/plugins/scopes.rb +19 -3
- data/lib/mongo_mapper/version.rb +1 -1
- data/spec/examples.txt +1685 -1674
- data/spec/functional/associations/belongs_to_proxy_spec.rb +18 -0
- data/spec/functional/associations/one_embedded_proxy_spec.rb +28 -0
- data/spec/functional/associations/one_proxy_spec.rb +11 -1
- data/spec/functional/dirty_spec.rb +21 -0
- data/spec/functional/dirty_with_callbacks_spec.rb +59 -0
- data/spec/functional/scopes_spec.rb +88 -0
- data/spec/unit/associations/proxy_spec.rb +12 -0
- metadata +3 -2
@@ -269,4 +269,22 @@ describe "BelongsToProxy" do
|
|
269
269
|
end.should_not raise_error
|
270
270
|
end
|
271
271
|
end
|
272
|
+
|
273
|
+
context "foreign_key=" do
|
274
|
+
it "should reset parent when foreign key is changed" do
|
275
|
+
post = @post_class.create!
|
276
|
+
comment = @comment_class.create!(post: post)
|
277
|
+
another_post = @post_class.create!
|
278
|
+
|
279
|
+
comment.post.should == post
|
280
|
+
|
281
|
+
comment.post_id = another_post.id
|
282
|
+
|
283
|
+
comment.post.should == another_post
|
284
|
+
|
285
|
+
comment.post_id = nil
|
286
|
+
|
287
|
+
comment.post.should == nil
|
288
|
+
end
|
289
|
+
end
|
272
290
|
end
|
@@ -97,4 +97,32 @@ describe "OneEmbeddedProxy" do
|
|
97
97
|
post.author.address.id.should_not be_nil
|
98
98
|
end
|
99
99
|
|
100
|
+
it "should keep the reference to assigned document" do
|
101
|
+
@post_class.one(:author, :class => @author_class)
|
102
|
+
post = @post_class.new
|
103
|
+
new_author = @author_class.new
|
104
|
+
post.author = new_author
|
105
|
+
new_author.name = 'Frank'
|
106
|
+
|
107
|
+
post.author.name.should == 'Frank'
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should update references for parent and root" do
|
111
|
+
@post_class.key(:author_name, String)
|
112
|
+
@post_class.one(:author, :class => @author_class)
|
113
|
+
@post_class.before_save do
|
114
|
+
self.author_name = author.name
|
115
|
+
end
|
116
|
+
|
117
|
+
author = @author_class.new
|
118
|
+
@post_class.create!(author: author)
|
119
|
+
author.save!
|
120
|
+
|
121
|
+
post = @post_class.create!(author: author)
|
122
|
+
post.author.name = 'Frank'
|
123
|
+
post.author.save!
|
124
|
+
|
125
|
+
post.author.name.should == 'Frank'
|
126
|
+
post.author_name.should == 'Frank'
|
127
|
+
end
|
100
128
|
end
|
@@ -403,4 +403,14 @@ describe "OneProxy" do
|
|
403
403
|
article.paper_id.should == @paper.id
|
404
404
|
end
|
405
405
|
end
|
406
|
-
|
406
|
+
|
407
|
+
it "should keep the reference to assigned document" do
|
408
|
+
@post_class.one(:author, :class => @author_class)
|
409
|
+
post = @post_class.new
|
410
|
+
new_author = @author_class.new
|
411
|
+
post.author = new_author
|
412
|
+
new_author.name = 'Frank'
|
413
|
+
|
414
|
+
post.author.name.should == 'Frank'
|
415
|
+
end
|
416
|
+
end
|
@@ -280,6 +280,27 @@ describe "Dirty" do
|
|
280
280
|
end
|
281
281
|
end
|
282
282
|
|
283
|
+
context "Document having Array key with typecast option" do
|
284
|
+
before do
|
285
|
+
@author_id = BSON::ObjectId.new
|
286
|
+
@doc = Doc('Book') { key :author_ids, Array, typecast: "ObjectId" }
|
287
|
+
@doc.plugin MongoMapper::Plugins::Dirty
|
288
|
+
@book = @doc.create!(author_ids: [@author_id])
|
289
|
+
end
|
290
|
+
|
291
|
+
context "changed" do
|
292
|
+
it "should be empty if assigned the same array" do
|
293
|
+
@book.author_ids = [@author_id]
|
294
|
+
@book.changed.should be_empty
|
295
|
+
end
|
296
|
+
|
297
|
+
it "should be empty if assigned the same but before-typecasted array" do
|
298
|
+
@book.author_ids = [@author_id.to_s]
|
299
|
+
@book.changed.should be_empty
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
283
304
|
context "Embedded documents" do
|
284
305
|
before do
|
285
306
|
@edoc = EDoc('Duck') { key :name, String }
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'DirtyWithCallbacks' do
|
4
|
+
it 'should update its changes/previous_changes before after_create/after_update callbacks' do
|
5
|
+
history = {}
|
6
|
+
|
7
|
+
document = Doc {
|
8
|
+
key :x, String
|
9
|
+
|
10
|
+
after_save {
|
11
|
+
history[:after_save] = {
|
12
|
+
changes: changes,
|
13
|
+
previous_changes: previous_changes,
|
14
|
+
}
|
15
|
+
}
|
16
|
+
after_create {
|
17
|
+
history[:after_create] = {
|
18
|
+
changes: changes,
|
19
|
+
previous_changes: previous_changes,
|
20
|
+
}
|
21
|
+
}
|
22
|
+
after_update {
|
23
|
+
history[:after_update] = {
|
24
|
+
changes: changes,
|
25
|
+
previous_changes: previous_changes,
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
d = document.new(x: 'hello')
|
31
|
+
d.save
|
32
|
+
|
33
|
+
history.should == {
|
34
|
+
after_save: {
|
35
|
+
changes: {},
|
36
|
+
previous_changes: {'x' => [nil, 'hello']},
|
37
|
+
},
|
38
|
+
after_create: {
|
39
|
+
changes: {},
|
40
|
+
previous_changes: {'x' => [nil, 'hello']},
|
41
|
+
},
|
42
|
+
}
|
43
|
+
history.clear
|
44
|
+
|
45
|
+
d.x = 'world'
|
46
|
+
d.save!
|
47
|
+
|
48
|
+
history.should == {
|
49
|
+
after_save: {
|
50
|
+
changes: {},
|
51
|
+
previous_changes: {'x' => ['hello', 'world']},
|
52
|
+
},
|
53
|
+
after_update: {
|
54
|
+
changes: {},
|
55
|
+
previous_changes: {'x' => ['hello', 'world']},
|
56
|
+
},
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
@@ -200,6 +200,19 @@ describe "Scopes" do
|
|
200
200
|
Blog.scopes.keys.map(&:to_s).should =~ %w(by_slug by_title published)
|
201
201
|
end
|
202
202
|
end
|
203
|
+
|
204
|
+
context 'with predefined class method name' do
|
205
|
+
it 'should raise ArgumentError' do
|
206
|
+
bad_names = %i(private public protected allocate new name parent superclass reload)
|
207
|
+
bad_names.each do |bad_name|
|
208
|
+
-> {
|
209
|
+
Doc() do
|
210
|
+
scope bad_name, -> {}
|
211
|
+
end
|
212
|
+
}.should raise_error(ArgumentError, /You tried to define a scope named "#{bad_name}"/)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
203
216
|
end
|
204
217
|
|
205
218
|
describe "with_scope" do
|
@@ -434,4 +447,79 @@ describe "Scopes" do
|
|
434
447
|
@klass.unsent.sorted.all.should == [two_days_ago, one_day_ago]
|
435
448
|
end
|
436
449
|
end
|
450
|
+
|
451
|
+
describe "thread safety" do
|
452
|
+
before do
|
453
|
+
@klass = Doc do
|
454
|
+
key :name, String
|
455
|
+
end
|
456
|
+
|
457
|
+
@threads = []
|
458
|
+
end
|
459
|
+
|
460
|
+
after do
|
461
|
+
@threads.each do |thread|
|
462
|
+
thread.kill
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
def make_thread(&block)
|
467
|
+
Thread.new(&block).tap do |thread|
|
468
|
+
@threads << thread
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
def wait_for_threads!
|
473
|
+
@threads.each { |t| t.join }
|
474
|
+
end
|
475
|
+
|
476
|
+
it "should not taint another thread's active scopes" do
|
477
|
+
count_active_scopes = nil
|
478
|
+
second_thread_run = false
|
479
|
+
|
480
|
+
make_thread do
|
481
|
+
@klass.with_scope(name: 'foo') do
|
482
|
+
loop do
|
483
|
+
sleep Float::EPSILON
|
484
|
+
break if second_thread_run
|
485
|
+
end
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
make_thread do
|
490
|
+
count_active_scopes = @klass.active_scopes.length
|
491
|
+
second_thread_run = true
|
492
|
+
end
|
493
|
+
|
494
|
+
wait_for_threads!
|
495
|
+
|
496
|
+
count_active_scopes.should == 0
|
497
|
+
end
|
498
|
+
|
499
|
+
it "should not taint another thread's count method" do
|
500
|
+
@klass.create!(name: 'foo')
|
501
|
+
@klass.create!(name: 'bar')
|
502
|
+
|
503
|
+
klass_count = nil
|
504
|
+
second_thread_run = false
|
505
|
+
|
506
|
+
make_thread do
|
507
|
+
@klass.with_scope(name: 'foo') do
|
508
|
+
loop do
|
509
|
+
sleep Float::EPSILON
|
510
|
+
break if second_thread_run
|
511
|
+
end
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
515
|
+
make_thread do
|
516
|
+
klass_count = @klass.count
|
517
|
+
second_thread_run = true
|
518
|
+
end
|
519
|
+
|
520
|
+
wait_for_threads!
|
521
|
+
|
522
|
+
klass_count.should == 2
|
523
|
+
end
|
524
|
+
end
|
437
525
|
end
|
@@ -95,5 +95,17 @@ describe "Proxy" do
|
|
95
95
|
p = Proc.new {|x| x+1}
|
96
96
|
@proxy.send(:collect, &p).should == [2,3]
|
97
97
|
end
|
98
|
+
|
99
|
+
it "should not respond to private method" do
|
100
|
+
@proxy.reload # To load @proxy.target
|
101
|
+
@proxy.target.extend(Module.new do
|
102
|
+
private
|
103
|
+
|
104
|
+
def private_foo
|
105
|
+
end
|
106
|
+
end)
|
107
|
+
|
108
|
+
lambda { @proxy.private_foo }.should raise_error(NoMethodError, /private method `private_foo' called/)
|
109
|
+
end
|
98
110
|
end
|
99
111
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongo_mapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.15.
|
4
|
+
version: 0.15.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Nunemaker
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2021-02-01 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: mongo
|
@@ -224,6 +224,7 @@ files:
|
|
224
224
|
- spec/functional/callbacks_spec.rb
|
225
225
|
- spec/functional/counter_cache_spec.rb
|
226
226
|
- spec/functional/dirty_spec.rb
|
227
|
+
- spec/functional/dirty_with_callbacks_spec.rb
|
227
228
|
- spec/functional/document_spec.rb
|
228
229
|
- spec/functional/dumpable_spec.rb
|
229
230
|
- spec/functional/dynamic_querying_spec.rb
|