mongoid 7.1.8 → 7.1.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.md +1 -1
- data/lib/mongoid/errors/mongoid_error.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/rails/generators/mongoid/config/templates/mongoid.yml +1 -1
- data/spec/integration/app_spec.rb +3 -0
- data/spec/mongoid/document_query_spec.rb +51 -0
- data/spec/mongoid/errors/mongoid_error_spec.rb +20 -8
- data/spec/mongoid/persistable_spec.rb +2 -2
- 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 +20 -6
- data/spec/shared/lib/mrss/docker_runner.rb +7 -1
- data/spec/shared/lib/mrss/spec_organizer.rb +18 -1
- data/spec/shared/share/Dockerfile.erb +121 -30
- data/spec/shared/share/haproxy-1.conf +16 -0
- data/spec/shared/share/haproxy-2.conf +17 -0
- data/spec/shared/shlib/server.sh +31 -4
- data/spec/shared/shlib/set_env.sh +4 -1
- data/spec/spec_helper.rb +1 -1
- metadata +481 -473
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f135a295b5c2604e02f7f9b47ada8f3c2ad7a00e63d834f2a02a965dd181c5c
|
4
|
+
data.tar.gz: 9ee16d88d4acd88f467c6e7152bb877cf21b64e94e2970094dc706399dd26c45
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e237e1208ce73ccb6081e81a5470b989b0085752790cdefe6a0482c202aa61343774f1972580b0c5f161fe9de7deb3bbbf97b4fcf1af33d466b9115bef32c8f
|
7
|
+
data.tar.gz: 58dc8d96b5ec060c3dbb9e953528e20d290ab54c0624661260730c25952b513df936abc6d6a4bb3a7090123938b6c819b723877c92431bb2e35265dcf1de0bff
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/README.md
CHANGED
@@ -34,15 +34,15 @@ module Mongoid
|
|
34
34
|
document.errors.add(
|
35
35
|
attribute,
|
36
36
|
:blank_in_locale,
|
37
|
-
options.merge(location: _locale)
|
37
|
+
**options.merge(location: _locale)
|
38
38
|
) if not_present?(_value)
|
39
39
|
end
|
40
40
|
elsif document.relations.has_key?(attribute.to_s)
|
41
41
|
if relation_or_fk_missing?(document, attribute, value)
|
42
|
-
document.errors.add(attribute, :blank, options)
|
42
|
+
document.errors.add(attribute, :blank, **options)
|
43
43
|
end
|
44
44
|
else
|
45
|
-
document.errors.add(attribute, :blank, options) if not_present?(value)
|
45
|
+
document.errors.add(attribute, :blank, **options) if not_present?(value)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -68,7 +68,7 @@ module Mongoid
|
|
68
68
|
# @since 2.4.10
|
69
69
|
def add_error(document, attribute, value)
|
70
70
|
document.errors.add(
|
71
|
-
attribute, :taken, options.except(:case_sensitive, :scope).merge(value: value)
|
71
|
+
attribute, :taken, **options.except(:case_sensitive, :scope).merge(value: value)
|
72
72
|
)
|
73
73
|
end
|
74
74
|
|
data/lib/mongoid/version.rb
CHANGED
@@ -57,7 +57,7 @@ development:
|
|
57
57
|
# connect: :direct
|
58
58
|
|
59
59
|
# Changes the default time in seconds the server monitors refresh their status
|
60
|
-
# via
|
60
|
+
# via hello commands. (default: 10)
|
61
61
|
# heartbeat_frequency: 10
|
62
62
|
|
63
63
|
# The time in seconds for selecting servers for a near read preference. (default: 0.015)
|
@@ -297,6 +297,9 @@ describe 'Mongoid application tests' do
|
|
297
297
|
end
|
298
298
|
|
299
299
|
def remove_bundler_req
|
300
|
+
return unless File.file?('Gemfile.lock')
|
301
|
+
# TODO: Remove this method completely when we get rid of .lock files in
|
302
|
+
# mongoid-demo apps.
|
300
303
|
lock_lines = IO.readlines('Gemfile.lock')
|
301
304
|
# Get rid of the bundled with line so that whatever bundler is installed
|
302
305
|
# on the system is usable with the application.
|
@@ -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
|
@@ -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)
|
@@ -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
|
@@ -52,7 +52,7 @@ module Mrss
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def require_topology(*topologies)
|
55
|
-
invalid_topologies = topologies - [:single, :replica_set, :sharded]
|
55
|
+
invalid_topologies = topologies - [:single, :replica_set, :sharded, :load_balanced]
|
56
56
|
|
57
57
|
unless invalid_topologies.empty?
|
58
58
|
raise ArgumentError, "Invalid topologies requested: #{invalid_topologies.join(', ')}"
|
@@ -82,7 +82,7 @@ module Mrss
|
|
82
82
|
unless ClusterConfig.instance.server_version >= '4.0'
|
83
83
|
skip 'Transactions tests in a replica set topology require server 4.0+'
|
84
84
|
end
|
85
|
-
when :sharded
|
85
|
+
when :sharded, :load_balanced
|
86
86
|
unless ClusterConfig.instance.server_version >= '4.2'
|
87
87
|
skip 'Transactions tests in a sharded cluster topology require server 4.2+'
|
88
88
|
end
|
@@ -249,7 +249,9 @@ module Mrss
|
|
249
249
|
# (mongos 4.0+ overrides the write concern)
|
250
250
|
def require_set_write_concern
|
251
251
|
before(:all) do
|
252
|
-
if ClusterConfig.instance.topology
|
252
|
+
if %i(sharded load_balanced).include?(ClusterConfig.instance.topology) &&
|
253
|
+
ClusterConfig.instance.short_server_version >= '4.0'
|
254
|
+
then
|
253
255
|
skip "mongos 4.0+ overrides write concern"
|
254
256
|
end
|
255
257
|
end
|
@@ -273,7 +275,9 @@ module Mrss
|
|
273
275
|
|
274
276
|
def require_wired_tiger
|
275
277
|
before(:all) do
|
276
|
-
|
278
|
+
# Storage detection fails for serverless instances. However, it is safe to
|
279
|
+
# assume that a serverless instance uses WiredTiger Storage Engine.
|
280
|
+
if !SpecConfig.instance.serverless? && ClusterConfig.instance.storage_engine != :wired_tiger
|
277
281
|
skip 'Test requires WiredTiger storage engine'
|
278
282
|
end
|
279
283
|
end
|
@@ -282,7 +286,9 @@ module Mrss
|
|
282
286
|
def require_wired_tiger_on_36
|
283
287
|
before(:all) do
|
284
288
|
if ClusterConfig.instance.short_server_version >= '3.6'
|
285
|
-
|
289
|
+
# Storage detection fails for serverless instances. However, it is safe to
|
290
|
+
# assume that a serverless instance uses WiredTiger Storage Engine.
|
291
|
+
if !SpecConfig.instance.serverless? && ClusterConfig.instance.storage_engine != :wired_tiger
|
286
292
|
skip 'Test requires WiredTiger storage engine on 3.6+ servers'
|
287
293
|
end
|
288
294
|
end
|
@@ -291,7 +297,7 @@ module Mrss
|
|
291
297
|
|
292
298
|
def require_mmapv1
|
293
299
|
before(:all) do
|
294
|
-
if ClusterConfig.instance.storage_engine != :mmapv1
|
300
|
+
if SpecConfig.instance.serverless? || ClusterConfig.instance.storage_engine != :mmapv1
|
295
301
|
skip 'Test requires MMAPv1 storage engine'
|
296
302
|
end
|
297
303
|
end
|
@@ -350,5 +356,13 @@ module Mrss
|
|
350
356
|
end
|
351
357
|
end
|
352
358
|
end
|
359
|
+
|
360
|
+
def require_unix_socket
|
361
|
+
before(:all) do
|
362
|
+
if ENV['TOPOLOGY'] == 'load-balanced'
|
363
|
+
skip 'Load balancer does not listen on Unix sockets'
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
353
367
|
end
|
354
368
|
end
|
@@ -111,7 +111,7 @@ module Mrss
|
|
111
111
|
'.'])
|
112
112
|
end
|
113
113
|
|
114
|
-
BASE_TEST_COMMAND = %w(docker run -i --tmpfs /tmpfs:exec).freeze
|
114
|
+
BASE_TEST_COMMAND = %w(docker run --rm -i --tmpfs /tmpfs:exec).freeze
|
115
115
|
|
116
116
|
def run_tests
|
117
117
|
run_command(BASE_TEST_COMMAND + tty_arg + extra_env + [image_tag] +
|
@@ -179,9 +179,11 @@ module Mrss
|
|
179
179
|
BASE_IMAGES = {
|
180
180
|
'debian81' => 'debian:jessie',
|
181
181
|
'debian92' => 'debian:stretch',
|
182
|
+
'debian10' => 'debian:buster',
|
182
183
|
'ubuntu1404' => 'ubuntu:trusty',
|
183
184
|
'ubuntu1604' => 'ubuntu:xenial',
|
184
185
|
'ubuntu1804' => 'ubuntu:bionic',
|
186
|
+
'ubuntu2004' => 'ubuntu:focal',
|
185
187
|
'rhel62' => 'centos:6',
|
186
188
|
'rhel70' => 'centos:7',
|
187
189
|
}.freeze
|
@@ -198,6 +200,10 @@ module Mrss
|
|
198
200
|
ruby == 'ruby-head'
|
199
201
|
end
|
200
202
|
|
203
|
+
def system_ruby?
|
204
|
+
%w(1 true yes).include?(@env['SYSTEM_RUBY']&.downcase)
|
205
|
+
end
|
206
|
+
|
201
207
|
def server_version
|
202
208
|
@env['MONGODB_VERSION']
|
203
209
|
end
|