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.
@@ -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
- end
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.1
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: 2020-10-03 00:00:00.000000000 Z
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