mongoid 7.2.2 → 7.2.6
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
- checksums.yaml.gz.sig +0 -0
- data/README.md +1 -1
- data/lib/config/locales/en.yml +13 -0
- data/lib/mongoid/association/embedded/embeds_many/proxy.rb +1 -1
- data/lib/mongoid/association/proxy.rb +1 -1
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +1 -1
- data/lib/mongoid/association/referenced/has_many/proxy.rb +1 -1
- data/lib/mongoid/association/relatable.rb +2 -0
- data/lib/mongoid/config/environment.rb +9 -1
- data/lib/mongoid/contextual/atomic.rb +7 -2
- data/lib/mongoid/contextual/none.rb +3 -0
- data/lib/mongoid/criteria/queryable/selectable.rb +2 -2
- data/lib/mongoid/criteria/queryable/storable.rb +4 -4
- data/lib/mongoid/criteria.rb +1 -1
- data/lib/mongoid/document.rb +3 -2
- data/lib/mongoid/errors/empty_config_file.rb +26 -0
- data/lib/mongoid/errors/invalid_config_file.rb +26 -0
- data/lib/mongoid/errors/mongoid_error.rb +1 -1
- data/lib/mongoid/errors.rb +2 -0
- data/lib/mongoid/interceptable.rb +1 -1
- data/lib/mongoid/persistence_context.rb +3 -1
- data/lib/mongoid/query_cache.rb +11 -1
- data/lib/mongoid/tasks/database.rb +1 -1
- data/lib/mongoid/validatable/associated.rb +1 -1
- data/lib/mongoid/validatable/presence.rb +3 -3
- data/lib/mongoid/validatable/uniqueness.rb +1 -1
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid.rb +1 -0
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +1 -1
- data/spec/integration/app_spec.rb +3 -0
- data/spec/integration/contextual/empty_spec.rb +142 -0
- data/spec/integration/stringified_symbol_field_spec.rb +2 -2
- data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +17 -4
- data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +17 -0
- data/spec/mongoid/association/referenced/belongs_to_query_spec.rb +20 -0
- data/spec/mongoid/association/referenced/has_many_models.rb +17 -0
- data/spec/mongoid/clients/factory_spec.rb +9 -3
- data/spec/mongoid/clients/options_spec.rb +11 -3
- data/spec/mongoid/config/environment_spec.rb +86 -8
- data/spec/mongoid/contextual/atomic_spec.rb +64 -25
- data/spec/mongoid/contextual/geo_near_spec.rb +1 -1
- data/spec/mongoid/criteria_spec.rb +4 -0
- data/spec/mongoid/document_fields_spec.rb +26 -0
- data/spec/mongoid/document_query_spec.rb +51 -0
- data/spec/mongoid/document_spec.rb +21 -1
- data/spec/mongoid/errors/invalid_config_file_spec.rb +32 -0
- data/spec/mongoid/errors/mongoid_error_spec.rb +20 -8
- data/spec/mongoid/persistable/updatable_spec.rb +2 -0
- data/spec/mongoid/persistable_spec.rb +2 -2
- data/spec/mongoid/query_cache_spec.rb +24 -0
- data/spec/shared/bin/s3-copy +45 -0
- data/spec/shared/bin/s3-upload +69 -0
- data/spec/shared/lib/mrss/cluster_config.rb +8 -3
- data/spec/shared/lib/mrss/constraints.rb +49 -10
- data/spec/shared/lib/mrss/docker_runner.rb +7 -1
- data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
- data/spec/shared/lib/mrss/server_version_registry.rb +17 -12
- data/spec/shared/lib/mrss/spec_organizer.rb +29 -2
- data/spec/shared/share/Dockerfile.erb +127 -35
- data/spec/shared/share/haproxy-1.conf +16 -0
- data/spec/shared/share/haproxy-2.conf +17 -0
- data/spec/shared/shlib/server.sh +100 -23
- data/spec/shared/shlib/set_env.sh +4 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/support/models/address.rb +4 -0
- data/spec/support/models/mop.rb +10 -0
- data/spec/support/models/person.rb +9 -0
- data.tar.gz.sig +0 -0
- metadata +549 -519
- metadata.gz.sig +0 -0
@@ -3769,10 +3769,14 @@ describe Mongoid::Criteria do
|
|
3769
3769
|
|
3770
3770
|
before do
|
3771
3771
|
expect(Person).to receive(:minor).and_call_original
|
3772
|
+
expect(Person).to receive(:older_than).and_call_original
|
3772
3773
|
end
|
3773
3774
|
|
3774
3775
|
it "calls the method on the class" do
|
3775
3776
|
expect(criteria.minor).to be_empty
|
3777
|
+
expect do
|
3778
|
+
criteria.older_than(age: 25)
|
3779
|
+
end.not_to raise_error
|
3776
3780
|
end
|
3777
3781
|
end
|
3778
3782
|
|
@@ -85,4 +85,30 @@ describe Mongoid::Document do
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
88
|
+
|
89
|
+
context 'Regexp field' do
|
90
|
+
shared_examples "persists strings as regexp" do |type|
|
91
|
+
it 'persists strings as regexp' do
|
92
|
+
mop = Mop.create!(regexp_field: 'foo')
|
93
|
+
expect(mop.regexp_field).to be_a Regexp
|
94
|
+
expect(Mop.find(mop.id).regexp_field).to be_a BSON::Regexp::Raw
|
95
|
+
expect(
|
96
|
+
Mop.collection.find(
|
97
|
+
"_id" => mop.id,
|
98
|
+
"regexp_field" => { "$type" => type }
|
99
|
+
).count
|
100
|
+
).to be == 1
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context "< 3.2" do
|
105
|
+
max_server_version("3.1")
|
106
|
+
include_examples "persists strings as regexp", 11
|
107
|
+
end
|
108
|
+
|
109
|
+
context ">= 3.2" do
|
110
|
+
min_server_version("3.2")
|
111
|
+
it_behaves_like "persists strings as regexp", "regex"
|
112
|
+
end
|
113
|
+
end
|
88
114
|
end
|
@@ -36,4 +36,55 @@ describe Mongoid::Document do
|
|
36
36
|
expect(_person.age).to be 42
|
37
37
|
end
|
38
38
|
end
|
39
|
+
|
40
|
+
context 'when projecting with #without' do
|
41
|
+
before do
|
42
|
+
duck = Pet.new(name: 'Duck')
|
43
|
+
Person.create!(username: 'Dev', title: 'CEO', pet: duck)
|
44
|
+
end
|
45
|
+
|
46
|
+
let(:person) { Person.where(username: 'Dev').without(:title).first }
|
47
|
+
|
48
|
+
it 'allows access to attribute of embedded document' do
|
49
|
+
expect(person.pet.name).to eq 'Duck'
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when exclusion starts with association name but is not the association' do
|
53
|
+
|
54
|
+
let(:person) { Person.where(username: 'Dev').without(:pet_).first }
|
55
|
+
|
56
|
+
it 'allows access to attribute of embedded document' do
|
57
|
+
expect(person.pet.name).to eq 'Duck'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'when exclusion starts with prefix of association name' do
|
62
|
+
|
63
|
+
let(:person) { Person.where(username: 'Dev').without(:pe).first }
|
64
|
+
|
65
|
+
it 'allows access to attribute of embedded document' do
|
66
|
+
expect(person.pet.name).to eq 'Duck'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when another attribute of the association is excluded' do
|
71
|
+
|
72
|
+
let(:person) { Person.where(username: 'Dev').without('pet.weight').first }
|
73
|
+
|
74
|
+
it 'allows access to non-excluded attribute of embedded document' do
|
75
|
+
expect(person.pet.name).to eq 'Duck'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'when the excluded attribute of the association is retrieved' do
|
80
|
+
|
81
|
+
let(:person) { Person.where(username: 'Dev').without('pet.name').first }
|
82
|
+
|
83
|
+
it 'prohibits the retrieval' do
|
84
|
+
lambda do
|
85
|
+
person.pet.name
|
86
|
+
end.should raise_error(ActiveModel::MissingAttributeError)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
39
90
|
end
|
@@ -501,7 +501,7 @@ describe Mongoid::Document do
|
|
501
501
|
end
|
502
502
|
end
|
503
503
|
|
504
|
-
context ':compact option' do
|
504
|
+
context 'deprecated :compact option' do
|
505
505
|
# Since rails 6 differs in how it treats id fields,
|
506
506
|
# run this test on one version of rails. Currently rails 6 is in beta,
|
507
507
|
# when it is released this version should be changed to 6.
|
@@ -513,6 +513,26 @@ describe Mongoid::Document do
|
|
513
513
|
expect(church.as_json.keys.sort).to eq(%w(_id location name))
|
514
514
|
end
|
515
515
|
|
516
|
+
context 'deprecation' do
|
517
|
+
let(:church) do
|
518
|
+
Church.create!(name: 'St. Basil')
|
519
|
+
end
|
520
|
+
|
521
|
+
let(:message) do
|
522
|
+
'#as_json :compact option is deprecated. Please call #compact on the returned Hash object instead.'
|
523
|
+
end
|
524
|
+
|
525
|
+
it 'logs a deprecation warning when :compact is given' do
|
526
|
+
expect_any_instance_of(Logger).to receive(:warn).with(message)
|
527
|
+
church.as_json(compact: true)
|
528
|
+
end
|
529
|
+
|
530
|
+
it 'does not log a deprecation warning when :compact is not given' do
|
531
|
+
expect_any_instance_of(Logger).to_not receive(:warn).with(message)
|
532
|
+
church.as_json
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
516
536
|
context 'there is a nil valued attribute' do
|
517
537
|
let(:church) do
|
518
538
|
Church.create!(name: 'St. Basil')
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require "spec_helper"
|
5
|
+
|
6
|
+
describe Mongoid::Errors::InvalidConfigFile do
|
7
|
+
|
8
|
+
describe "#message" do
|
9
|
+
|
10
|
+
let(:error) do
|
11
|
+
described_class.new('/my/path')
|
12
|
+
end
|
13
|
+
|
14
|
+
it "contains the problem in the message" do
|
15
|
+
expect(error.message).to include(
|
16
|
+
"Invalid configuration file: /my/path."
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "contains the summary in the message" do
|
21
|
+
expect(error.message).to include(
|
22
|
+
"Your mongoid.yml configuration file does not contain the"
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "contains the resolution in the message" do
|
27
|
+
expect(error.message).to include(
|
28
|
+
"Ensure your configuration file contains the correct contents."
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -10,14 +10,26 @@ describe Mongoid::Errors::MongoidError do
|
|
10
10
|
let(:options) { {} }
|
11
11
|
|
12
12
|
before do
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
if RUBY_VERSION.start_with?('3.', '2.7')
|
14
|
+
{"message_title" => "message", "summary_title" => "summary", "resolution_title" => "resolution"}.each do |key, name|
|
15
|
+
expect(::I18n).to receive(:translate).with("mongoid.errors.messages.#{key}", **{}).and_return(name)
|
16
|
+
end
|
17
|
+
|
18
|
+
["message", "summary", "resolution"].each do |name|
|
19
|
+
expect(::I18n).to receive(:translate).
|
20
|
+
with("mongoid.errors.messages.#{key}.#{name}", **{}).
|
21
|
+
and_return(name)
|
22
|
+
end
|
23
|
+
else
|
24
|
+
{"message_title" => "message", "summary_title" => "summary", "resolution_title" => "resolution"}.each do |key, name|
|
25
|
+
expect(::I18n).to receive(:translate).with("mongoid.errors.messages.#{key}", {}).and_return(name)
|
26
|
+
end
|
27
|
+
|
28
|
+
["message", "summary", "resolution"].each do |name|
|
29
|
+
expect(::I18n).to receive(:translate).
|
30
|
+
with("mongoid.errors.messages.#{key}.#{name}", {}).
|
31
|
+
and_return(name)
|
32
|
+
end
|
21
33
|
end
|
22
34
|
|
23
35
|
error.compose_message(key, options)
|
@@ -458,6 +458,7 @@ describe Mongoid::Persistable::Updatable do
|
|
458
458
|
describe "##{method}" do
|
459
459
|
|
460
460
|
context "when saving with a hash field with invalid keys" do
|
461
|
+
max_server_version '4.9'
|
461
462
|
|
462
463
|
let(:person) do
|
463
464
|
Person.create
|
@@ -494,6 +495,7 @@ describe Mongoid::Persistable::Updatable do
|
|
494
495
|
end
|
495
496
|
|
496
497
|
context "when the document has been destroyed" do
|
498
|
+
max_server_version '4.9'
|
497
499
|
|
498
500
|
let(:person) do
|
499
501
|
Person.create
|
@@ -24,10 +24,27 @@ describe Mongoid::QueryCache do
|
|
24
24
|
SessionRegistry.instance.verify_sessions_ended!
|
25
25
|
end
|
26
26
|
|
27
|
+
let(:reset_legacy_qc_warning) do
|
28
|
+
begin
|
29
|
+
Mongoid::QueryCache.remove_instance_variable('@legacy_query_cache_warned')
|
30
|
+
rescue NameError
|
31
|
+
# raised if the instance variable wasn't set
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
27
35
|
describe '#cache' do
|
28
36
|
context 'with driver query cache' do
|
29
37
|
min_driver_version '2.14'
|
30
38
|
|
39
|
+
it 'does not log a deprecation warning' do
|
40
|
+
reset_legacy_qc_warning
|
41
|
+
|
42
|
+
expect_any_instance_of(Logger).to_not receive(:warn).with(
|
43
|
+
described_class::LEGACY_WARNING
|
44
|
+
)
|
45
|
+
described_class.cache { }
|
46
|
+
end
|
47
|
+
|
31
48
|
context 'when query cache is not enabled' do
|
32
49
|
before do
|
33
50
|
Mongoid::QueryCache.enabled = false
|
@@ -180,6 +197,13 @@ describe Mongoid::QueryCache do
|
|
180
197
|
context 'with mongoid query cache' do
|
181
198
|
max_driver_version '2.13'
|
182
199
|
|
200
|
+
it 'logs a deprecation warning' do
|
201
|
+
reset_legacy_qc_warning
|
202
|
+
|
203
|
+
expect_any_instance_of(Logger).to receive(:warn).with(described_class::LEGACY_WARNING)
|
204
|
+
described_class.cache { }
|
205
|
+
end
|
206
|
+
|
183
207
|
context 'when query cache is not enabled' do
|
184
208
|
before do
|
185
209
|
Mongoid::QueryCache.enabled = false
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'aws-sdk-s3'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
OptionParser.new do |opts|
|
8
|
+
opts.banner = "Usage: s3-copy options"
|
9
|
+
|
10
|
+
opts.on("-r", "--region=REGION", "AWS region to use (default us-east-1)") do |v|
|
11
|
+
options[:region] = v
|
12
|
+
end
|
13
|
+
|
14
|
+
opts.on("-p", "--param=KEY=VALUE", "Specify parameter for new files") do |v|
|
15
|
+
options[:params] ||= {}
|
16
|
+
k, v = v.split('=', 2)
|
17
|
+
options[:params][k.to_sym] = v
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on("-f", "--from=BUCKET:PATH", "Bucket name and key (or path) to copy from") do |v|
|
21
|
+
options[:from] = v
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on("-t", "--to=BUCKET:PATH", "Bucket name and key (or path) to write to (may be specified more than once)") do |v|
|
25
|
+
options[:to] ||= []
|
26
|
+
options[:to] << v
|
27
|
+
end
|
28
|
+
end.parse!
|
29
|
+
|
30
|
+
ENV['AWS_REGION'] ||= options[:region] || 'us-east-1'
|
31
|
+
|
32
|
+
bucket, key = options.fetch(:from).split(':', 2)
|
33
|
+
|
34
|
+
s3 = Aws::S3::Client.new
|
35
|
+
|
36
|
+
options.fetch(:to).each do |dest|
|
37
|
+
STDERR.puts "Copying to #{dest}"
|
38
|
+
dbucket, dkey = dest.split(':', 2)
|
39
|
+
s3.copy_object(
|
40
|
+
bucket: dbucket,
|
41
|
+
key: dkey,
|
42
|
+
copy_source: "/#{bucket}/#{key}",
|
43
|
+
**options[:params] || {},
|
44
|
+
)
|
45
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'aws-sdk-s3'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
OptionParser.new do |opts|
|
8
|
+
opts.banner = "Usage: s3-upload options"
|
9
|
+
|
10
|
+
opts.on("-r", "--region=REGION", "AWS region to use (default us-east-1)") do |v|
|
11
|
+
options[:region] = v
|
12
|
+
end
|
13
|
+
|
14
|
+
opts.on("-p", "--param=KEY=VALUE", "Specify parameter for S3 upload") do |v|
|
15
|
+
options[:params] ||= {}
|
16
|
+
k, v = v.split('=', 2)
|
17
|
+
options[:params][k.to_sym] = v
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on("-f", "--file=PATH", "Path to the file to upload, - to upload standard input") do |v|
|
21
|
+
options[:file] = v
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on("-w", "--write=BUCKET:PATH", "Bucket name and key (or path) to upload to") do |v|
|
25
|
+
options[:write] = v
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on("-c", "--copy=BUCKET:PATH", "Bucket name and key (or path) to copy to (may be specified more than once)") do |v|
|
29
|
+
options[:copy] ||= []
|
30
|
+
options[:copy] << v
|
31
|
+
end
|
32
|
+
end.parse!
|
33
|
+
|
34
|
+
ENV['AWS_REGION'] ||= options[:region] || 'us-east-1'
|
35
|
+
|
36
|
+
def upload(f, options)
|
37
|
+
s3 = Aws::S3::Client.new
|
38
|
+
write = options.fetch(:write)
|
39
|
+
STDERR.puts "Writing #{write}"
|
40
|
+
bucket, key = write.split(':', 2)
|
41
|
+
s3.put_object(
|
42
|
+
body: f.read,
|
43
|
+
bucket: bucket,
|
44
|
+
key: key,
|
45
|
+
**options[:params] || {},
|
46
|
+
)
|
47
|
+
if copy = options[:copy]
|
48
|
+
copy.each do |dest|
|
49
|
+
STDERR.puts "Copying to #{dest}"
|
50
|
+
dbucket, dkey = dest.split(':', 2)
|
51
|
+
s3.copy_object(
|
52
|
+
bucket: dbucket,
|
53
|
+
key: dkey,
|
54
|
+
copy_source: "/#{bucket}/#{key}",
|
55
|
+
**options[:params] || {},
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
if options[:file] == '-'
|
62
|
+
upload(STDIN, options)
|
63
|
+
elsif options[:file]
|
64
|
+
File.open(options[:file]) do |f|
|
65
|
+
upload(f, options)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
upload(STDIN, options)
|
69
|
+
end
|
@@ -15,6 +15,11 @@ module Mrss
|
|
15
15
|
@single_server
|
16
16
|
end
|
17
17
|
|
18
|
+
def sharded_ish?
|
19
|
+
determine_cluster_config
|
20
|
+
@topology == :sharded || @topology == :load_balanced
|
21
|
+
end
|
22
|
+
|
18
23
|
def replica_set_name
|
19
24
|
determine_cluster_config
|
20
25
|
@replica_set_name
|
@@ -48,7 +53,7 @@ module Mrss
|
|
48
53
|
raise "Deployment server version not known - check that connection to deployment succeeded"
|
49
54
|
end
|
50
55
|
|
51
|
-
if server_version >= '3.4' &&
|
56
|
+
if server_version >= '3.4' && !sharded_ish?
|
52
57
|
fcv
|
53
58
|
else
|
54
59
|
if short_server_version == '4.1'
|
@@ -115,7 +120,7 @@ module Mrss
|
|
115
120
|
:mmapv1
|
116
121
|
else
|
117
122
|
client = ClientRegistry.instance.global_client('root_authorized')
|
118
|
-
if
|
123
|
+
if sharded_ish?
|
119
124
|
shards = client.use(:admin).command(listShards: 1).first
|
120
125
|
if shards['shards'].empty?
|
121
126
|
raise 'Shards are empty'
|
@@ -206,7 +211,7 @@ module Mrss
|
|
206
211
|
|
207
212
|
@server_parameters = client.use(:admin).command(getParameter: '*').first
|
208
213
|
|
209
|
-
if
|
214
|
+
if !sharded_ish? && short_server_version >= '3.4'
|
210
215
|
rv = @server_parameters['featureCompatibilityVersion']
|
211
216
|
@fcv = rv['version'] || rv
|
212
217
|
end
|