mongo_mapper 0.15.5 → 0.16.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.
@@ -10,10 +10,14 @@ module CallbacksSupport
10
10
  :before_save, :after_save,
11
11
  :before_destroy, :after_destroy
12
12
  ].each do |callback|
13
- base.send(callback) do
13
+ base.send(callback, if: :always_true) do
14
14
  history << callback.to_sym
15
15
  end
16
16
  end
17
+
18
+ base.send(:define_method, :always_true) do
19
+ true
20
+ end
17
21
  end
18
22
 
19
23
  def history
@@ -51,6 +51,39 @@ describe "EmbeddedDocument" do
51
51
  doc.foo._parent_document.should be(doc)
52
52
  doc.foo._root_document.should be(doc)
53
53
  end
54
+
55
+ context "given subclass of embedded document" do
56
+ before do
57
+ @sub_address_class = Subclass(@address_class, 'SubAddress')
58
+ end
59
+
60
+ it "should embed embedded document" do
61
+ address = @sub_address_class.new(:city => 'South Bend', :state => 'IN')
62
+ doc = @klass.create(:foo => address)
63
+ doc.foo.city.should == 'South Bend'
64
+ doc.foo.state.should == 'IN'
65
+
66
+ doc = doc.reload
67
+ doc.foo.city.should == 'South Bend'
68
+ doc.foo.state.should == 'IN'
69
+ end
70
+
71
+ it "should assign _parent_document and _root_document" do
72
+ address = @sub_address_class.new(:city => 'South Bend', :state => 'IN')
73
+ address._parent_document.should be_nil
74
+ doc = @klass.create(:foo => address)
75
+ address._parent_document.should be(doc)
76
+ address._root_document.should be(doc)
77
+ end
78
+
79
+ it "should assign _parent_document and _root_document when loading" do
80
+ address = @sub_address_class.new(:city => 'South Bend', :state => 'IN')
81
+ doc = @klass.create(:foo => address)
82
+ doc.reload
83
+ doc.foo._parent_document.should be(doc)
84
+ doc.foo._root_document.should be(doc)
85
+ end
86
+ end
54
87
  end
55
88
 
56
89
  it "should correctly instantiate single collection inherited embedded documents" do
@@ -367,4 +367,80 @@ describe "Keys" do
367
367
  instance.a_num.should == 10
368
368
  end
369
369
  end
370
+
371
+ describe 'default value is child of embedded class' do
372
+ class EmbeddedParent
373
+ include MongoMapper::EmbeddedDocument
374
+ end
375
+ class EmbeddedChild < EmbeddedParent
376
+ end
377
+
378
+ context 'with type' do
379
+ class DocumentWithEmbeddedAndDefaultValue
380
+ include MongoMapper::Document
381
+ key :my_embedded, EmbeddedParent, default: -> { EmbeddedChild.new }
382
+ end
383
+
384
+ it "should work" do
385
+ instance = DocumentWithEmbeddedAndDefaultValue.new
386
+ instance.my_embedded.should be_instance_of(EmbeddedChild)
387
+ end
388
+ end
389
+
390
+ context 'without type' do
391
+ class DocumentWithEmbeddedAndDefaultValueWithoutType
392
+ include MongoMapper::Document
393
+ key :my_embedded, EmbeddedParent, default: -> { EmbeddedChild.new }
394
+ end
395
+
396
+ it "should work" do
397
+ instance = DocumentWithEmbeddedAndDefaultValueWithoutType.new
398
+ instance.my_embedded.should be_instance_of(EmbeddedChild)
399
+ end
400
+ end
401
+ end
402
+
403
+ describe 'default value is a custom class' do
404
+ class TimeOfDay
405
+ attr_reader :seconds
406
+
407
+ def initialize(seconds)
408
+ @seconds = seconds
409
+ end
410
+
411
+ def self.from_mongo(value)
412
+ return nil if value.blank?
413
+
414
+ new(value.to_i)
415
+ end
416
+
417
+ def self.to_mongo(value)
418
+ return nil if value.blank?
419
+
420
+ value.seconds
421
+ end
422
+ end
423
+
424
+ context 'with type' do
425
+ class DocumentWithCustomClass
426
+ include MongoMapper::Document
427
+ key :my_embedded, TimeOfDay, default: -> { TimeOfDay.new(900) }
428
+ end
429
+ it "should work" do
430
+ instance = DocumentWithCustomClass.new
431
+ instance.my_embedded.should be_instance_of(TimeOfDay)
432
+ end
433
+ end
434
+
435
+ context 'without type' do
436
+ class DocumentWithCustomClassWithoutType
437
+ include MongoMapper::Document
438
+ key :my_embedded, default: -> { TimeOfDay.new(900) }
439
+ end
440
+ it "should work" do
441
+ instance = DocumentWithCustomClass.new
442
+ instance.my_embedded.should be_instance_of(TimeOfDay)
443
+ end
444
+ end
445
+ end
370
446
  end
@@ -1,65 +1,57 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'Shardable' do
4
- let(:sharded_model) {
5
- Doc do
6
- key :first_name, String
7
- key :last_name, String
8
- shard_key :first_name, :last_name
9
- end
10
- }
11
-
12
4
  describe 'shard_key_fields' do
13
5
  it 'returns declared field names' do
14
- sharded_model.shard_key_fields.should == ['first_name', 'last_name']
6
+ ShardedModel.shard_key_fields.should == ['first_name']
15
7
  end
16
8
  end
17
9
 
18
10
  describe 'shard_key_filter' do
19
11
  context 'new record' do
20
- let(:document) { sharded_model.new(first_name: 'John', last_name: 'Smith') }
12
+ let(:document) { ShardedModel.new(first_name: 'John', last_name: 'Smith') }
21
13
 
22
14
  it 'returns current values' do
23
- document.shard_key_filter.should == { 'first_name' => 'John', 'last_name' => 'Smith' }
15
+ document.shard_key_filter.should == { 'first_name' => 'John' }
24
16
  end
25
17
  end
26
18
 
27
19
  context 'persisted record' do
28
- let(:document) { sharded_model.create!(first_name: 'John', last_name: 'Smith') }
20
+ let(:document) { ShardedModel.create!(first_name: 'John', last_name: 'Smith') }
29
21
 
30
22
  before do
31
23
  document.first_name = 'William'
32
24
  end
33
25
 
34
26
  it 'returns persisted values' do
35
- document.shard_key_filter.should == { 'first_name' => 'John', 'last_name' => 'Smith' }
27
+ document.shard_key_filter.should == { 'first_name' => 'John' }
36
28
  end
37
29
  end
38
30
  end
39
31
 
40
32
  context 'creating new document' do
41
- let(:document) { sharded_model.new(first_name: 'John', last_name: 'Smith') }
33
+ let(:document) { ShardedModel.new(first_name: 'John', last_name: 'Smith') }
42
34
 
43
35
  it 'inserts new document' do
44
- lambda { document.save! }.should change { sharded_model.count }.by(1)
36
+ lambda { document.save! }.should change { ShardedModel.count }.by(1)
45
37
 
46
- persisted = sharded_model.find(document.id)
38
+ persisted = ShardedModel.find(document.id)
47
39
  persisted.first_name.should == 'John'
48
40
  persisted.last_name.should == 'Smith'
49
41
  end
50
42
  end
51
43
 
52
44
  context 'updating persisted document' do
53
- let(:document) { sharded_model.create!(first_name: 'John', last_name: 'Smith') }
45
+ let(:document) { ShardedModel.create!(first_name: 'John', last_name: 'Smith') }
54
46
 
55
47
  before do
56
48
  document.first_name = 'William'
57
49
  end
58
50
 
59
51
  it 'updates persisted document' do
60
- lambda { document.save! }.should_not change { sharded_model.count }
52
+ lambda { document.save! }.should_not change { ShardedModel.count }
61
53
 
62
- persisted = sharded_model.find(document.id)
54
+ persisted = ShardedModel.find(document.id)
63
55
  persisted.first_name.should == 'William'
64
56
  persisted.last_name.should == 'Smith'
65
57
  end
data/spec/spec_helper.rb CHANGED
@@ -69,6 +69,18 @@ def EDoc(name='Class', &block)
69
69
  klass
70
70
  end
71
71
 
72
+ def Subclass(super_class, name='Subclass', &block)
73
+ klass = Class.new(super_class) do
74
+ if name
75
+ class_eval "def self.name; '#{name}' end"
76
+ class_eval "def self.to_s; '#{name}' end"
77
+ end
78
+ end
79
+
80
+ klass.class_eval(&block) if block_given?
81
+ klass
82
+ end
83
+
72
84
  def drop_indexes(klass)
73
85
  klass.collection.indexes.drop_all if klass.database.collection_names.include?(klass.collection.name)
74
86
  end
@@ -0,0 +1,24 @@
1
+ class ShardedModel
2
+ include MongoMapper::Document
3
+
4
+ key :first_name, String
5
+ key :last_name, String
6
+ shard_key :first_name
7
+ end
8
+
9
+ if ENV.fetch("ENABLE_SHARDING", "0") == "1"
10
+ client = MongoMapper.connection
11
+ database = MongoMapper.database
12
+
13
+ # https://www.mongodb.com/docs/manual/reference/command/enableSharding/#mongodb-dbcommand-dbcmd.enableSharding
14
+ client.use(:admin).command(enableSharding: database.name)
15
+
16
+ # https://www.mongodb.com/docs/manual/reference/command/shardCollection/#mongodb-dbcommand-dbcmd.shardCollection
17
+ # Note: this command automatically creates the index for the empty collection
18
+ client.use(:admin).command(
19
+ shardCollection: [database.name, ShardedModel.collection.name].join("."),
20
+ key: {
21
+ first_name: "hashed",
22
+ },
23
+ )
24
+ end
@@ -88,7 +88,7 @@ describe "Document" do
88
88
  end
89
89
 
90
90
  it "should be recorded" do
91
- Message.descendants.should == [Enter, Exit, Chat]
91
+ Message.descendants.should contain_exactly(Enter, Exit, Chat)
92
92
  end
93
93
  end
94
94
 
@@ -220,10 +220,10 @@ describe "EmbeddedDocument" do
220
220
  end
221
221
 
222
222
  it "should be recorded" do
223
- Grandparent.direct_descendants.should == [Parent]
224
- Grandparent.descendants.to_set.should == [Parent, Child, OtherChild].to_set
223
+ Grandparent.direct_descendants.should contain_exactly(Parent)
224
+ Grandparent.descendants.to_set.should contain_exactly(Parent, Child, OtherChild)
225
225
 
226
- Parent.descendants.should == [Child, OtherChild]
226
+ Parent.descendants.should contain_exactly(Child, OtherChild)
227
227
  end
228
228
  end
229
229
  end
@@ -44,4 +44,54 @@ describe "Inspect" do
44
44
  doc.inspect.should =~ /_id:.*, pet: .*_id.*, name: "Kitten".*/
45
45
  end
46
46
  end
47
+
48
+ context "#inspect with filter_attributes" do
49
+ before do
50
+ MongoMapper::Utils.remove_instance_variable(:@filter) if MongoMapper::Utils.instance_variable_defined?(:@filter)
51
+ MongoMapper.filter_attributes = [:email, :card_number, :phone_number]
52
+ end
53
+
54
+ after do
55
+ MongoMapper.filter_attributes =[]
56
+ MongoMapper::Utils.remove_instance_variable(:@filter) if MongoMapper::Utils.instance_variable_defined?(:@filter)
57
+ end
58
+
59
+ it "should filter the fields given by filter_attributes" do
60
+ document = Doc('User') do
61
+ key :name, String
62
+ key :age, Integer
63
+ key :email, String
64
+ key :card_number, String
65
+ end
66
+ doc = document.new(
67
+ :name => 'John',
68
+ :age => 29,
69
+ :email => 'mongomapper@example.com',
70
+ :card_number => '123'
71
+ )
72
+
73
+ if ActiveSupport.version >= Gem::Version.new("6.0")
74
+ doc.inspect.should =~ /_id:.*, age: 29, card_number: \[FILTERED\], email: \[FILTERED\], name: "John"/
75
+ else
76
+ doc.inspect.should =~ /_id:.*, age: 29, card_number: "123", email: "mongomapper@example.com", name: "John"/
77
+ end
78
+ end
79
+
80
+ it "should filter the fields given by filter_attributes for embedded document" do
81
+ document = EDoc('Profile') do
82
+ key :job, String
83
+ key :phone_number, String
84
+ end
85
+ doc = document.new(
86
+ :job => 'Software Engineer',
87
+ :phone_number => '09011110000'
88
+ )
89
+
90
+ if ActiveSupport.version >= Gem::Version.new("6.0")
91
+ doc.inspect.should =~ /job: "Software Engineer", phone_number: \[FILTERED\]/
92
+ else
93
+ doc.inspect.should =~ /job: "Software Engineer", phone_number: "09011110000"/
94
+ end
95
+ end
96
+ end
47
97
  end
@@ -276,6 +276,17 @@ describe "Key" do
276
276
  it "should work with procs" do
277
277
  Key.new(:foo, String, :default => lambda { return 'hello world' }).default_value.should == "hello world"
278
278
  end
279
+
280
+ it "should work with embedded document" do
281
+ embedded = EDoc()
282
+ Key.new(:foo, embedded, :default => lambda { embedded.new }).default_value.should be_instance_of(embedded)
283
+ end
284
+
285
+ it "should work with subclass of embedded document" do
286
+ embedded = EDoc()
287
+ subclass = Subclass(embedded)
288
+ Key.new(:foo, embedded, :default => lambda { subclass.new }).default_value.should be_instance_of(subclass)
289
+ end
279
290
  end
280
291
  end
281
292
  end # KeyTest
@@ -71,7 +71,7 @@ describe "MongoMapper" do
71
71
  'development' => {'hosts' => ['127.0.0.1:27017'], 'database' => 'test', 'read' => 'primary'}
72
72
  }
73
73
  logger = double('logger')
74
- Mongo::Client.should_receive(:new).with(['127.0.0.1:27017'], :logger => logger, :read => :primary, :database => 'test')
74
+ Mongo::Client.should_receive(:new).with(['127.0.0.1:27017'], { :logger => logger, :read => :primary, :database => 'test' })
75
75
  MongoMapper.connect('development', :logger => logger)
76
76
  end
77
77
 
@@ -80,7 +80,7 @@ describe "MongoMapper" do
80
80
  'development' => {'hosts' => ['192.168.1.1:2222'], 'database' => 'test', 'safe' => true}
81
81
  }
82
82
  logger = double('logger')
83
- Mongo::Client.should_receive(:new).with(['192.168.1.1:2222'], :logger => logger, :safe => true, :database => 'test')
83
+ Mongo::Client.should_receive(:new).with(['192.168.1.1:2222'], { :logger => logger, :safe => true, :database => 'test' })
84
84
  MongoMapper.connect('development', :logger => logger)
85
85
  end
86
86
 
@@ -89,7 +89,7 @@ describe "MongoMapper" do
89
89
  'development' => {'uri' => 'mongodb://127.0.0.1:27017/test', 'options'=> {:foo => 1}}
90
90
  }
91
91
  logger = double('logger')
92
- Mongo::Client.should_receive(:new).with('mongodb://127.0.0.1:27017/test', :logger => logger, :foo => 1)
92
+ Mongo::Client.should_receive(:new).with('mongodb://127.0.0.1:27017/test', { :logger => logger, :foo => 1 })
93
93
  MongoMapper.connect('development', :logger => logger)
94
94
  end
95
95
 
@@ -97,7 +97,7 @@ describe "MongoMapper" do
97
97
  MongoMapper.config = {
98
98
  'development' => {'hosts' => ['127.0.0.1:27017'], 'database' => 'test', 'user' => 'john', 'password' => 'secret'}
99
99
  }
100
- Mongo::Client.should_receive(:new).with(['127.0.0.1:27017'], :database => 'test', :user => 'john', :password => 'secret')
100
+ Mongo::Client.should_receive(:new).with(['127.0.0.1:27017'], { :database => 'test', :user => 'john', :password => 'secret' })
101
101
  MongoMapper.connect('development')
102
102
  end
103
103
 
@@ -129,9 +129,23 @@ describe "MongoMapper" do
129
129
  it "should work as shortcut for setting config, environment and options" do
130
130
  config, logger = double('config'), double('logger')
131
131
  MongoMapper.should_receive(:config=).with(config)
132
- MongoMapper.should_receive(:connect).with('development', :logger => logger)
132
+ MongoMapper.should_receive(:connect).with('development', { :logger => logger })
133
133
  MongoMapper.should_receive(:handle_passenger_forking).once
134
134
  MongoMapper.setup(config, 'development', :logger => logger)
135
135
  end
136
+
137
+ it "should use the right reconnect method" do
138
+ Mongo::Client.instance_methods.should_not include(:connect) # v1
139
+ Mongo::Client.instance_methods.should include(:reconnect) # v1
140
+ end
141
+ end
142
+
143
+ context "options" do
144
+ it "should sets/returns filtered_attributes correctly" do
145
+ MongoMapper.filter_attributes.should == []
146
+ filtered_attributes = [:password, :credit_number]
147
+ MongoMapper.filter_attributes = filtered_attributes
148
+ MongoMapper.filter_attributes.should == filtered_attributes
149
+ end
136
150
  end
137
151
  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.5
4
+ version: 0.16.0
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: 2022-02-18 00:00:00.000000000 Z
13
+ date: 2023-10-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: mongo
@@ -125,6 +125,7 @@ files:
125
125
  - examples/validating/embedded_docs.rb
126
126
  - lib/mongo_mapper.rb
127
127
  - lib/mongo_mapper/connection.rb
128
+ - lib/mongo_mapper/deprecator.rb
128
129
  - lib/mongo_mapper/document.rb
129
130
  - lib/mongo_mapper/embedded_document.rb
130
131
  - lib/mongo_mapper/exceptions.rb
@@ -145,6 +146,7 @@ files:
145
146
  - lib/mongo_mapper/extensions/time.rb
146
147
  - lib/mongo_mapper/locale/en.yml
147
148
  - lib/mongo_mapper/middleware/identity_map.rb
149
+ - lib/mongo_mapper/options.rb
148
150
  - lib/mongo_mapper/plugins.rb
149
151
  - lib/mongo_mapper/plugins/accessible.rb
150
152
  - lib/mongo_mapper/plugins/active_model.rb
@@ -271,6 +273,7 @@ files:
271
273
  - spec/spec_helper.rb
272
274
  - spec/support/matchers.rb
273
275
  - spec/support/models.rb
276
+ - spec/support/sharded_model.rb
274
277
  - spec/unit/associations/base_spec.rb
275
278
  - spec/unit/associations/belongs_to_association_spec.rb
276
279
  - spec/unit/associations/many_association_spec.rb
@@ -320,7 +323,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
320
323
  - !ruby/object:Gem::Version
321
324
  version: '0'
322
325
  requirements: []
323
- rubygems_version: 3.1.6
326
+ rubygems_version: 3.3.7
324
327
  signing_key:
325
328
  specification_version: 4
326
329
  summary: A Ruby Object Mapper for Mongo