mongoid 7.2.5 → 7.2.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +3 -3
  3. data/lib/config/locales/en.yml +13 -0
  4. data/lib/mongoid/association/relatable.rb +2 -0
  5. data/lib/mongoid/config/environment.rb +9 -1
  6. data/lib/mongoid/contextual/atomic.rb +7 -2
  7. data/lib/mongoid/contextual/none.rb +3 -0
  8. data/lib/mongoid/criteria/queryable/selectable.rb +2 -2
  9. data/lib/mongoid/criteria/queryable/storable.rb +4 -4
  10. data/lib/mongoid/document.rb +3 -2
  11. data/lib/mongoid/errors/empty_config_file.rb +26 -0
  12. data/lib/mongoid/errors/invalid_config_file.rb +26 -0
  13. data/lib/mongoid/errors.rb +2 -0
  14. data/lib/mongoid/persistence_context.rb +3 -1
  15. data/lib/mongoid/query_cache.rb +11 -1
  16. data/lib/mongoid/tasks/database.rb +1 -1
  17. data/lib/mongoid/version.rb +1 -1
  18. data/spec/integration/contextual/empty_spec.rb +142 -0
  19. data/spec/integration/stringified_symbol_field_spec.rb +2 -2
  20. data/spec/mongoid/association/referenced/belongs_to_query_spec.rb +20 -0
  21. data/spec/mongoid/association/referenced/has_many_models.rb +17 -0
  22. data/spec/mongoid/clients/factory_spec.rb +9 -3
  23. data/spec/mongoid/clients/options_spec.rb +11 -5
  24. data/spec/mongoid/config/environment_spec.rb +86 -8
  25. data/spec/mongoid/contextual/atomic_spec.rb +64 -25
  26. data/spec/mongoid/contextual/geo_near_spec.rb +1 -1
  27. data/spec/mongoid/document_spec.rb +21 -1
  28. data/spec/mongoid/errors/invalid_config_file_spec.rb +32 -0
  29. data/spec/mongoid/persistable/updatable_spec.rb +2 -0
  30. data/spec/mongoid/query_cache_spec.rb +24 -0
  31. data/spec/shared/lib/mrss/constraints.rb +21 -4
  32. data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
  33. data/spec/shared/lib/mrss/server_version_registry.rb +17 -12
  34. data/spec/shared/share/Dockerfile.erb +5 -4
  35. data/spec/shared/shlib/server.sh +71 -21
  36. data.tar.gz.sig +0 -0
  37. metadata +544 -536
  38. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48a874132bc5ad122d06af32088dc9d274a7f22be5c103c7ffd4b02e7d7ab665
4
- data.tar.gz: 295479a0affc8ed42a63765e75fef536d1465a7d35742df6fba76f0d27ae6ae5
3
+ metadata.gz: e421b4ac00142136b0a04a14e31c432c95d6fc040dd54a606b4a26f5028ef04e
4
+ data.tar.gz: cb252a745ffcf28e5da18a2f6d8007be05403af3c81d3f35307608acc19c99b5
5
5
  SHA512:
6
- metadata.gz: b2ab81319ae56b679033c2dcb6d0f4dbe3324ab38c2e6ded3c3a79a044f3a346162fedd79054f91a97823944fbb2d1e9ac90a301e56135ac7d139a8e4cfdeb04
7
- data.tar.gz: 02d0cfefc3a885ac256a683112467536f4e0adae1b0c3e216e1dfa34c27137f226fa445ced26e9d02a8d45bd4482af100c491dd83aef9f6ea87d6f4de7653c9f
6
+ metadata.gz: 5ad32c694837c1ebb182f7082b084b57680d20f47306745f2c58c9af7eab41058acfa877e73e25d731bdb84d103f761ff8aca7fb13d49d7ecd1c846491581f4a
7
+ data.tar.gz: b8b329017900e2405af3bb183f824ee3bb5e43bca44784ea0a43895c03ce2bb650e9862395f6118bb346dc02dc838fc997b900e9b24e5ce7b1e84f0c81948538
checksums.yaml.gz.sig CHANGED
@@ -1,3 +1,3 @@
1
- ��a[h�?wiNCH'��#3� ���ڒ��ʱ�� Fc]o�G�)����� YlB����Oy"̯��Y���!GFZ��,�2Zh�+����(Rȧ��:�*wI����P9G�rϝ9Ç����ɜI��*2���GH�嶉%*�h�
2
- ��?�����[��ٝ��.Ό3�V�;CI���U��aKR�P�����E�z�Ph)��1�i� �0��5��E
3
- s��k��_w��-�D����&?���!i:�|:
1
+ C-�%&��b��� �3������d?�jW6?���A�A���s��+-��S�~���e8{F=��qF��|��M�ey�R$�ː�ӎ^:���Sl��Q�W��@D�u #=���I��;j�o�"�&��C���)�=i�C��G�� uބ@\��Sv�����/��|ԲIc��]!-�d�E�ׇ,5����Ɍ��_��^��edJ��ҍ�Zd�sO�W������I���
2
+ �b��
3
+ �@�p2.�@�"NU6�
@@ -80,6 +80,12 @@ en:
80
80
  different collections so a simple id lookup is not sufficient enough."
81
81
  resolution: "Don't attempt to perform this action and have patience,
82
82
  maybe this will be supported in the future."
83
+ empty_config_file:
84
+ message: "Empty configuration file: %{path}."
85
+ summary: "Your mongoid.yml configuration file appears to be empty."
86
+ resolution: "Ensure your configuration file contains the correct contents.
87
+ Please consult the following page with respect to Mongoid's configuration:
88
+ https://docs.mongodb.com/mongoid/current/reference/configuration/"
83
89
  invalid_collection:
84
90
  message: "Access to the collection for %{klass} is not allowed."
85
91
  summary: "%{klass}.collection was called, and %{klass} is an embedded
@@ -94,6 +100,13 @@ en:
94
100
  A collation option is only supported if the query is executed on a MongoDB server
95
101
  with version >= 3.4."
96
102
  resolution: "Remove the collation option from the query."
103
+ invalid_config_file:
104
+ message: "Invalid configuration file: %{path}."
105
+ summary: "Your mongoid.yml configuration file does not contain the
106
+ correct file structure."
107
+ resolution: "Ensure your configuration file contains the correct contents.
108
+ Please consult the following page with respect to Mongoid's configuration:
109
+ https://docs.mongodb.com/mongoid/current/reference/configuration/"
97
110
  invalid_config_option:
98
111
  message: "Invalid configuration option: %{name}."
99
112
  summary: "A invalid configuration option was provided in your
@@ -122,6 +122,8 @@ module Mongoid
122
122
  # @since 7.0
123
123
  def inverses(other = nil)
124
124
  return [ inverse_of ] if inverse_of
125
+ return [] if @options.key?(:inverse_of) && !inverse_of
126
+
125
127
  if polymorphic?
126
128
  polymorphic_inverses(other)
127
129
  else
@@ -52,7 +52,15 @@ module Mongoid
52
52
  # @api private
53
53
  def load_yaml(path, environment = nil)
54
54
  env = environment ? environment.to_s : env_name
55
- YAML.load(ERB.new(File.new(path).read).result)[env]
55
+ contents = File.new(path).read
56
+ if contents.empty?
57
+ raise Mongoid::Errors::EmptyConfigFile.new(path)
58
+ end
59
+ data = YAML.load(ERB.new(contents).result)
60
+ unless data.is_a?(Hash)
61
+ raise Mongoid::Errors::InvalidConfigFile.new(path)
62
+ end
63
+ data[env]
56
64
  end
57
65
  end
58
66
  end
@@ -173,13 +173,18 @@ module Mongoid
173
173
  # @example Unset the field on the matches.
174
174
  # context.unset(:name)
175
175
  #
176
- # @param [ String, Symbol, Array ] args The name of the fields.
176
+ # @param [ String | Symbol | Array<String|Symbol> | Hash ] args
177
+ # The name(s) of the field(s) to unset.
178
+ # If a Hash is specified, its keys will be used irrespective of what
179
+ # each key's value is, even if the value is nil or false.
177
180
  #
178
181
  # @return [ nil ] Nil.
179
182
  #
180
183
  # @since 3.0.0
181
184
  def unset(*args)
182
- fields = args.__find_args__.collect { |f| [database_field_name(f), true] }
185
+ fields = args.map { |a| a.is_a?(Hash) ? a.keys : a }
186
+ .__find_args__
187
+ .map { |f| [database_field_name(f), true] }
183
188
  view.update_many("$unset" => Hash[fields])
184
189
  end
185
190
 
@@ -112,6 +112,9 @@ module Mongoid
112
112
  entries.length
113
113
  end
114
114
  alias :size :length
115
+
116
+ alias :find_first :first
117
+ alias :one :first
115
118
  end
116
119
  end
117
120
  end
@@ -597,7 +597,7 @@ module Mongoid
597
597
  end
598
598
  _mongoid_expand_keys(new_s).each do |k, v|
599
599
  k = k.to_s
600
- if c.selector[k] || k[0] == ?$
600
+ if c.selector[k] || k.start_with?('$')
601
601
  c = c.send(:__multi__, [{'$nor' => [{k => v}]}], '$and')
602
602
  else
603
603
  if v.is_a?(Hash)
@@ -889,7 +889,7 @@ module Mongoid
889
889
  end
890
890
  criterion.each do |field, value|
891
891
  field_s = field.to_s
892
- if field_s[0] == ?$
892
+ if field_s.start_with?('$')
893
893
  # Query expression-level operator, like $and or $where
894
894
  query.add_operator_expression(field_s, value)
895
895
  else
@@ -38,7 +38,7 @@ module Mongoid
38
38
  raise ArgumentError, "Field must be a string: #{field}"
39
39
  end
40
40
 
41
- if field[0] == ?$
41
+ if field.start_with?('$')
42
42
  raise ArgumentError, "Field cannot be an operator (i.e. begin with $): #{field}"
43
43
  end
44
44
 
@@ -48,7 +48,7 @@ module Mongoid
48
48
  if value.is_a?(Hash) && selector[field].is_a?(Hash) &&
49
49
  value.keys.all? { |key|
50
50
  key_s = key.to_s
51
- key_s[0] == ?$ && !selector[field].key?(key_s)
51
+ key_s.start_with?('$') && !selector[field].key?(key_s)
52
52
  }
53
53
  then
54
54
  # Multiple operators can be combined on the same field by
@@ -185,7 +185,7 @@ module Mongoid
185
185
  raise ArgumentError, "Operator must be a string: #{operator}"
186
186
  end
187
187
 
188
- unless operator[0] == ?$
188
+ unless operator.start_with?('$')
189
189
  raise ArgumentError, "Operator must begin with $: #{operator}"
190
190
  end
191
191
 
@@ -220,7 +220,7 @@ module Mongoid
220
220
  raise ArgumentError, "Field must be a string: #{field}"
221
221
  end
222
222
 
223
- if field[0] == ?$
223
+ if field.start_with?('$')
224
224
  add_operator_expression(field, value)
225
225
  else
226
226
  add_field_expression(field, value)
@@ -194,8 +194,8 @@ module Mongoid
194
194
  #
195
195
  # @param [ Hash ] options The options.
196
196
  #
197
- # @option options [ true, false ] :compact Whether to include fields with
198
- # nil values in the json document.
197
+ # @option options [ true, false ] :compact (Deprecated) Whether to include fields
198
+ # with nil values in the json document.
199
199
  #
200
200
  # @return [ Hash ] The document as json.
201
201
  #
@@ -203,6 +203,7 @@ module Mongoid
203
203
  def as_json(options = nil)
204
204
  rv = super
205
205
  if options && options[:compact]
206
+ Mongoid.logger.warn('#as_json :compact option is deprecated. Please call #compact on the returned Hash object instead.')
206
207
  rv = rv.compact
207
208
  end
208
209
  rv
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ module Mongoid
5
+ module Errors
6
+
7
+ # This error is raised when an empty configuration file is attempted to be
8
+ # loaded.
9
+ class EmptyConfigFile < MongoidError
10
+
11
+ # Create the new error.
12
+ #
13
+ # @param [ String ] path The path of the config file used.
14
+ #
15
+ # @api private
16
+ def initialize(path)
17
+ super(
18
+ compose_message(
19
+ "empty_config_file",
20
+ { path: path }
21
+ )
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ module Mongoid
5
+ module Errors
6
+
7
+ # This error is raised when a bad configuration file is attempted to be
8
+ # loaded.
9
+ class InvalidConfigFile < MongoidError
10
+
11
+ # Create the new error.
12
+ #
13
+ # @param [ String ] path The path of the config file used.
14
+ #
15
+ # @api private
16
+ def initialize(path)
17
+ super(
18
+ compose_message(
19
+ "invalid_config_file",
20
+ { path: path }
21
+ )
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
@@ -8,8 +8,10 @@ require "mongoid/errors/criteria_argument_required"
8
8
  require "mongoid/errors/document_not_destroyed"
9
9
  require "mongoid/errors/document_not_found"
10
10
  require "mongoid/errors/eager_load"
11
+ require "mongoid/errors/empty_config_file"
11
12
  require "mongoid/errors/in_memory_collation_not_supported"
12
13
  require "mongoid/errors/invalid_collection"
14
+ require "mongoid/errors/invalid_config_file"
13
15
  require "mongoid/errors/invalid_config_option"
14
16
  require "mongoid/errors/invalid_dependent_strategy"
15
17
  require "mongoid/errors/invalid_field"
@@ -237,7 +237,9 @@ module Mongoid
237
237
  # @since 6.0.0
238
238
  def clear(object, cluster = nil, original_context = nil)
239
239
  if context = get(object)
240
- context.client.close unless (context.cluster.equal?(cluster) || cluster.nil?)
240
+ unless cluster.nil? || context.cluster.equal?(cluster)
241
+ context.client.close
242
+ end
241
243
  end
242
244
  ensure
243
245
  Thread.current["[mongoid][#{object.object_id}]:context"] = original_context
@@ -7,8 +7,14 @@ module Mongoid
7
7
  #
8
8
  # @since 4.0.0
9
9
  module QueryCache
10
- class << self
10
+ # @api private
11
+ LEGACY_WARNING = <<~DOC
12
+ You are using the legacy Mongoid query cache which has known issues.
13
+ Please upgrade the `mongo' gem to at least 2.14.0 to use the improved driver query cache.
14
+ Refer to: https://docs.mongodb.com/mongoid/current/tutorials/mongoid-queries/#the-improved-driver-query-cache
15
+ DOC
11
16
 
17
+ class << self
12
18
  # Get the cached queries.
13
19
  #
14
20
  # @example Get the cached queries from the current thread.
@@ -86,6 +92,10 @@ module Mongoid
86
92
  if defined?(Mongo::QueryCache)
87
93
  Mongo::QueryCache.cache(&block)
88
94
  else
95
+ @legacy_query_cache_warned ||= begin
96
+ Mongoid.logger.warn(LEGACY_WARNING)
97
+ true
98
+ end
89
99
  enabled = QueryCache.enabled?
90
100
  QueryCache.enabled = true
91
101
  begin
@@ -123,7 +123,7 @@ module Mongoid
123
123
  next if model.shard_config.nil?
124
124
 
125
125
  if model.embedded? && !model.cyclic?
126
- logger.warn("MONGOID: #{model} has shard config but is emdedded")
126
+ logger.warn("MONGOID: #{model} has shard config but is embedded")
127
127
  next
128
128
  end
129
129
 
@@ -2,5 +2,5 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  module Mongoid
5
- VERSION = "7.2.5"
5
+ VERSION = "7.2.6"
6
6
  end
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require 'spec_helper'
5
+
6
+ describe 'Contextual classes when dealing with empty result set' do
7
+ shared_examples 'behave as expected' do
8
+ context '#exists?' do
9
+ it 'is false' do
10
+ context.exists?.should be false
11
+ end
12
+ end
13
+
14
+ context '#count' do
15
+ it 'is 0' do
16
+ context.count.should == 0
17
+ end
18
+ end
19
+
20
+ context '#length' do
21
+ it 'is 0' do
22
+ context.length.should == 0
23
+ end
24
+ end
25
+
26
+ # #estimated_count only exists for Mongo
27
+
28
+ context '#distinct' do
29
+ it 'is empty array' do
30
+ context.distinct(:foo).should == []
31
+ end
32
+ end
33
+
34
+ context '#each' do
35
+ context 'with block' do
36
+ it 'does not invoke the block' do
37
+ called = false
38
+ context.each do
39
+ called = true
40
+ end
41
+ called.should be false
42
+ end
43
+ end
44
+
45
+ context 'without block' do
46
+ it 'returns Enumerable' do
47
+ context.each.should be_a(Enumerable)
48
+ end
49
+
50
+ it 'returns empty Enumerable' do
51
+ context.each.to_a.should == []
52
+ end
53
+ end
54
+ end
55
+
56
+ context '#map' do
57
+ context 'with block' do
58
+ it 'does not invoke the block' do
59
+ called = false
60
+ context.map do
61
+ called = true
62
+ end
63
+ called.should be false
64
+ end
65
+ end
66
+
67
+ context 'without block' do
68
+ it 'returns empty array' do
69
+ skip 'MONGOID-5148'
70
+
71
+ context.map(:field).should == []
72
+ end
73
+ end
74
+ end
75
+
76
+ context '#first' do
77
+ it 'is nil' do
78
+ context.first.should be nil
79
+ end
80
+ end
81
+
82
+ context '#find_first' do
83
+ it 'is nil' do
84
+ context.find_first.should be nil
85
+ end
86
+ end
87
+
88
+ context '#one' do
89
+ it 'is nil' do
90
+ context.one.should be nil
91
+ end
92
+ end
93
+
94
+ context '#last' do
95
+ it 'is nil' do
96
+ context.last.should be nil
97
+ end
98
+ end
99
+ end
100
+
101
+ let(:context) do
102
+ context_cls.new(criteria)
103
+ end
104
+
105
+ before do
106
+ # Create an object of the same class used in the Criteria instance
107
+ # to verify we are using the Contextual classes.
108
+ Mop.create!
109
+ end
110
+
111
+ context 'Mongo' do
112
+ let(:context_cls) { Mongoid::Contextual::Mongo }
113
+
114
+ let(:criteria) do
115
+ Mop.and(Mop.where(a: 1), Mop.where(a: 2))
116
+ end
117
+
118
+ include_examples 'behave as expected'
119
+ end
120
+
121
+ context 'Memory' do
122
+ let(:context_cls) { Mongoid::Contextual::Memory }
123
+
124
+ let(:criteria) do
125
+ Mop.all.tap do |criteria|
126
+ criteria.documents = []
127
+ end
128
+ end
129
+
130
+ include_examples 'behave as expected'
131
+ end
132
+
133
+ context 'None' do
134
+ let(:context_cls) { Mongoid::Contextual::None }
135
+
136
+ let(:criteria) do
137
+ Mop.none
138
+ end
139
+
140
+ include_examples 'behave as expected'
141
+ end
142
+ end