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.
- checksums.yaml +4 -4
- data/README.md +5 -4
- data/lib/mongo_mapper/connection.rb +1 -1
- data/lib/mongo_mapper/deprecator.rb +7 -0
- data/lib/mongo_mapper/options.rb +13 -0
- data/lib/mongo_mapper/plugins/caching.rb +2 -2
- data/lib/mongo_mapper/plugins/embedded_callbacks.rb +2 -2
- data/lib/mongo_mapper/plugins/inspect.rb +4 -2
- data/lib/mongo_mapper/plugins/keys.rb +4 -2
- data/lib/mongo_mapper/plugins/strong_parameters.rb +6 -2
- data/lib/mongo_mapper/plugins.rb +18 -1
- data/lib/mongo_mapper/railtie.rb +12 -0
- data/lib/mongo_mapper/utils.rb +12 -0
- data/lib/mongo_mapper/version.rb +1 -1
- data/lib/mongo_mapper.rb +3 -0
- data/spec/examples.txt +1740 -1727
- data/spec/functional/callbacks_spec.rb +5 -1
- data/spec/functional/embedded_document_spec.rb +33 -0
- data/spec/functional/keys_spec.rb +76 -0
- data/spec/functional/shardable_spec.rb +11 -19
- data/spec/spec_helper.rb +12 -0
- data/spec/support/sharded_model.rb +24 -0
- data/spec/unit/document_spec.rb +1 -1
- data/spec/unit/embedded_document_spec.rb +3 -3
- data/spec/unit/inspect_spec.rb +50 -0
- data/spec/unit/key_spec.rb +11 -0
- data/spec/unit/mongo_mapper_spec.rb +19 -5
- metadata +6 -3
@@ -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
|
-
|
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) {
|
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'
|
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) {
|
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'
|
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) {
|
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 {
|
36
|
+
lambda { document.save! }.should change { ShardedModel.count }.by(1)
|
45
37
|
|
46
|
-
persisted =
|
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) {
|
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 {
|
52
|
+
lambda { document.save! }.should_not change { ShardedModel.count }
|
61
53
|
|
62
|
-
persisted =
|
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
|
data/spec/unit/document_spec.rb
CHANGED
@@ -220,10 +220,10 @@ describe "EmbeddedDocument" do
|
|
220
220
|
end
|
221
221
|
|
222
222
|
it "should be recorded" do
|
223
|
-
Grandparent.direct_descendants.should
|
224
|
-
Grandparent.descendants.to_set.should
|
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
|
226
|
+
Parent.descendants.should contain_exactly(Child, OtherChild)
|
227
227
|
end
|
228
228
|
end
|
229
229
|
end
|
data/spec/unit/inspect_spec.rb
CHANGED
@@ -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
|
data/spec/unit/key_spec.rb
CHANGED
@@ -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.
|
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:
|
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.
|
326
|
+
rubygems_version: 3.3.7
|
324
327
|
signing_key:
|
325
328
|
specification_version: 4
|
326
329
|
summary: A Ruby Object Mapper for Mongo
|