mongoid 7.0.6 → 7.0.12

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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +1 -1
  5. data/Rakefile +14 -5
  6. data/lib/mongoid.rb +1 -1
  7. data/lib/mongoid/association/embedded/embeds_many.rb +2 -1
  8. data/lib/mongoid/association/embedded/embeds_one.rb +2 -1
  9. data/lib/mongoid/association/proxy.rb +1 -1
  10. data/lib/mongoid/atomic.rb +13 -3
  11. data/lib/mongoid/clients/sessions.rb +20 -4
  12. data/lib/mongoid/criteria.rb +7 -1
  13. data/lib/mongoid/criteria/modifiable.rb +2 -1
  14. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  15. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +3 -3
  16. data/lib/mongoid/criteria/queryable/extensions/time.rb +1 -1
  17. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +12 -0
  18. data/lib/mongoid/document.rb +3 -2
  19. data/lib/mongoid/extensions/hash.rb +4 -2
  20. data/lib/mongoid/extensions/regexp.rb +1 -1
  21. data/lib/mongoid/fields.rb +2 -1
  22. data/lib/mongoid/interceptable.rb +3 -1
  23. data/lib/mongoid/matchable/regexp.rb +2 -2
  24. data/lib/mongoid/persistable/pushable.rb +11 -2
  25. data/lib/mongoid/persistence_context.rb +6 -6
  26. data/lib/mongoid/query_cache.rb +61 -18
  27. data/lib/mongoid/validatable/uniqueness.rb +1 -1
  28. data/lib/mongoid/version.rb +1 -1
  29. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
  30. data/spec/app/models/customer.rb +11 -0
  31. data/spec/app/models/customer_address.rb +12 -0
  32. data/spec/app/models/delegating_patient.rb +16 -0
  33. data/spec/integration/app_spec.rb +192 -0
  34. data/spec/integration/associations/embedded_spec.rb +62 -0
  35. data/spec/integration/callbacks_models.rb +49 -0
  36. data/spec/integration/callbacks_spec.rb +216 -0
  37. data/spec/integration/criteria/date_field_spec.rb +41 -0
  38. data/spec/integration/document_spec.rb +22 -0
  39. data/spec/lite_spec_helper.rb +12 -4
  40. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +50 -0
  41. data/spec/mongoid/association/embedded/embeds_many_models.rb +53 -0
  42. data/spec/mongoid/association/embedded/embeds_many_spec.rb +10 -0
  43. data/spec/mongoid/association/embedded/embeds_one_spec.rb +0 -2
  44. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +140 -1
  45. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +105 -0
  46. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +2 -1
  47. data/spec/mongoid/atomic/paths_spec.rb +41 -0
  48. data/spec/mongoid/clients/options_spec.rb +4 -4
  49. data/spec/mongoid/clients/sessions_spec.rb +8 -4
  50. data/spec/mongoid/clients/transactions_spec.rb +20 -8
  51. data/spec/mongoid/clients_spec.rb +2 -2
  52. data/spec/mongoid/contextual/atomic_spec.rb +20 -10
  53. data/spec/mongoid/contextual/geo_near_spec.rb +11 -2
  54. data/spec/mongoid/contextual/map_reduce_spec.rb +20 -5
  55. data/spec/mongoid/contextual/mongo_spec.rb +76 -53
  56. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +7 -7
  57. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +1 -1
  58. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +19 -7
  59. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +28 -1
  60. data/spec/mongoid/criteria_spec.rb +4 -2
  61. data/spec/mongoid/document_persistence_context_spec.rb +33 -0
  62. data/spec/mongoid/indexable_spec.rb +6 -4
  63. data/spec/mongoid/matchable/default_spec.rb +1 -1
  64. data/spec/mongoid/matchable/regexp_spec.rb +2 -2
  65. data/spec/mongoid/matchable_spec.rb +2 -2
  66. data/spec/mongoid/persistable/pushable_spec.rb +55 -1
  67. data/spec/mongoid/query_cache_spec.rb +77 -9
  68. data/spec/mongoid/relations/proxy_spec.rb +1 -1
  69. data/spec/mongoid/scopable_spec.rb +2 -1
  70. data/spec/mongoid/tasks/database_rake_spec.rb +13 -13
  71. data/spec/mongoid/tasks/database_spec.rb +1 -1
  72. data/spec/shared/LICENSE +20 -0
  73. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  74. data/spec/shared/lib/mrss/cluster_config.rb +211 -0
  75. data/spec/shared/lib/mrss/constraints.rb +330 -0
  76. data/spec/shared/lib/mrss/docker_runner.rb +262 -0
  77. data/spec/shared/lib/mrss/lite_constraints.rb +175 -0
  78. data/spec/shared/lib/mrss/server_version_registry.rb +69 -0
  79. data/spec/shared/lib/mrss/spec_organizer.rb +149 -0
  80. data/spec/shared/share/Dockerfile.erb +229 -0
  81. data/spec/shared/shlib/distro.sh +73 -0
  82. data/spec/shared/shlib/server.sh +270 -0
  83. data/spec/shared/shlib/set_env.sh +128 -0
  84. data/spec/spec_helper.rb +0 -31
  85. data/spec/support/child_process_helper.rb +76 -0
  86. data/spec/support/cluster_config.rb +3 -3
  87. data/spec/support/constraints.rb +201 -30
  88. data/spec/support/session_registry.rb +50 -0
  89. data/spec/support/spec_config.rb +12 -4
  90. metadata +510 -461
  91. metadata.gz.sig +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef857ba0b8faece9cb5bb46f2d1cb6e50fa1e2b52e6870c22cec4c5a3e73b98d
4
- data.tar.gz: 030fbeeabf03434eb695eef129dd7abc1304419b550937ae225c2edd33824570
3
+ metadata.gz: '08107532375c756a9a063a167169b570fa9d5f195e753a4f19a70ee7778eff1c'
4
+ data.tar.gz: addbf1ebd6dc0edc11a2604b4e3c1bf7297d67ad12739dcd44e981d2a8949cac
5
5
  SHA512:
6
- metadata.gz: 5e05da048526dece6963bfc5d33bb8e2db2ae3e26d37c9aa39949b9f69d16a93e33780bc7ce9244b23df11eb70e77d86cd95dfcd4426f864f3eb3429c0883033
7
- data.tar.gz: dbb8f110097c0184d6de55630aac584722944d345723cca7ecaf76719548798970e992ba051beeb9b3ed801a49b4a2b1397a04717597620ab0183967091b368a
6
+ metadata.gz: 77dbc0a24838853d496fd5957770ef250c952cf57a126b36845540e6421888aa3abc9465ecb64d0a55940324c02a7e22a37935729deec400b6d2f0510138930a
7
+ data.tar.gz: 0b78a7bbe3049aff86657a02e88f61ef4b8281f5cd198567bbe153d44f7f56d74eca7b0119a40d9b8188ffb0b78f73847abbba82b39b601220f177ef7ac80a61
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -14,7 +14,7 @@ Project Tracking
14
14
  ----------------
15
15
 
16
16
  * [Mongoid Website and Documentation](http://mongoid.org)
17
- * [Mongoid Google Group](http://groups.google.com/group/mongoid)
17
+ * [MongoDB Community Forum](https://developer.mongodb.com/community/forums/tags/c/drivers-odms-connectors/7/mongoid-odm)
18
18
  * [Stackoverflow](http://stackoverflow.com/questions/tagged/mongoid)
19
19
  * [#mongoid](http://webchat.freenode.net/?channels=mongoid) on freenode IRC
20
20
 
data/Rakefile CHANGED
@@ -1,4 +1,5 @@
1
1
  require "bundler"
2
+ require "bundler/gem_tasks"
2
3
  Bundler.setup
3
4
 
4
5
  require "rake"
@@ -7,6 +8,9 @@ require "rspec/core/rake_task"
7
8
  $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
8
9
  require "mongoid/version"
9
10
 
11
+ tasks = Rake.application.instance_variable_get('@tasks')
12
+ tasks['release:do'] = tasks.delete('release')
13
+
10
14
  task :gem => :build
11
15
  task :build do
12
16
  system "gem build mongoid.gemspec"
@@ -16,11 +20,8 @@ task :install => :build do
16
20
  system "sudo gem install mongoid-#{Mongoid::VERSION}.gem"
17
21
  end
18
22
 
19
- task :release => :build do
20
- system "git tag -a v#{Mongoid::VERSION} -m 'Tagging #{Mongoid::VERSION}'"
21
- system "git push --tags"
22
- system "gem push mongoid-#{Mongoid::VERSION}.gem"
23
- system "rm mongoid-#{Mongoid::VERSION}.gem"
23
+ task :release do
24
+ raise "Please use ./release.sh to release"
24
25
  end
25
26
 
26
27
  RSpec::Core::RakeTask.new("spec") do |spec|
@@ -45,3 +46,11 @@ namespace :docs do
45
46
  system "yardoc -o #{out} --title mongoid-#{Mongoid::VERSION}"
46
47
  end
47
48
  end
49
+
50
+ namespace :release do
51
+ task :check_private_key do
52
+ unless File.exist?('gem-private_key.pem')
53
+ raise "No private key present, cannot release"
54
+ end
55
+ end
56
+ end
data/lib/mongoid.rb CHANGED
@@ -102,5 +102,5 @@ module Mongoid
102
102
  # Mongoid.database = Mongo::Connection.new.db("test")
103
103
  #
104
104
  # @since 1.0.0
105
- delegate(*(Config.public_instance_methods(false) - [ :logger=, :logger ] << { to: Config }))
105
+ delegate(*(Config.public_instance_methods(false) - [ :logger=, :logger ]), to: Config)
106
106
  end
@@ -197,7 +197,8 @@ module Mongoid
197
197
  def determine_inverses(other)
198
198
  matches = relation_class.relations.values.select do |rel|
199
199
  relation_complements.include?(rel.class) &&
200
- rel.relation_class_name == inverse_class_name
200
+ # https://jira.mongodb.org/browse/MONGOID-4882
201
+ rel.relation_class_name.sub(/\A::/, '') == inverse_class_name
201
202
  end
202
203
  if matches.size > 1
203
204
  raise Errors::AmbiguousRelationship.new(relation_class, @owner_class, name, matches)
@@ -159,7 +159,8 @@ module Mongoid
159
159
  def determine_inverses(other)
160
160
  matches = relation_class.relations.values.select do |rel|
161
161
  relation_complements.include?(rel.class) &&
162
- rel.relation_class_name == inverse_class_name
162
+ # https://jira.mongodb.org/browse/MONGOID-4882
163
+ rel.relation_class_name.sub(/\A::/, '') == inverse_class_name
163
164
 
164
165
  end
165
166
  if matches.size > 1
@@ -12,7 +12,7 @@ module Mongoid
12
12
  # We undefine most methods to get them sent through to the target.
13
13
  instance_methods.each do |method|
14
14
  undef_method(method) unless
15
- method =~ /^(__.*|send|object_id|equal\?|respond_to\?|tap|public_send|extend_proxy|extend_proxies)$/
15
+ method =~ /\A(__.*|send|object_id|equal\?|respond_to\?|tap|public_send|extend_proxy|extend_proxies)\z/
16
16
  end
17
17
 
18
18
  include Threaded::Lifecycle
@@ -36,7 +36,9 @@ module Mongoid
36
36
  # @since 2.2.0
37
37
  def add_atomic_pull(document)
38
38
  document.flagged_for_destroy = true
39
- (delayed_atomic_pulls[document.association_name.to_s] ||= []).push(document)
39
+ key = document.association_name.to_s
40
+ delayed_atomic_pulls[key] ||= []
41
+ delayed_atomic_pulls[key] << document
40
42
  end
41
43
 
42
44
  # Add an atomic unset for the document.
@@ -51,7 +53,9 @@ module Mongoid
51
53
  # @since 3.0.0
52
54
  def add_atomic_unset(document)
53
55
  document.flagged_for_destroy = true
54
- (delayed_atomic_unsets[document.association_name.to_s] ||= []).push(document)
56
+ key = document.association_name.to_s
57
+ delayed_atomic_unsets[key] ||= []
58
+ delayed_atomic_unsets[key] << document
55
59
  end
56
60
 
57
61
  # Returns path of the attribute for modification
@@ -189,7 +193,13 @@ module Mongoid
189
193
  #
190
194
  # @since 2.1.0
191
195
  def atomic_paths
192
- @atomic_paths ||= _association ? _association.path(self) : Atomic::Paths::Root.new(self)
196
+ @atomic_paths ||= begin
197
+ if _association
198
+ _association.path(self)
199
+ else
200
+ Atomic::Paths::Root.new(self)
201
+ end
202
+ end
193
203
  end
194
204
 
195
205
  # Get all the attributes that need to be pulled.
@@ -38,12 +38,20 @@ module Mongoid
38
38
  #
39
39
  # @since 6.4.0
40
40
  def with_session(options = {})
41
- raise Mongoid::Errors::InvalidSessionUse.new(:invalid_session_nesting) if Threaded.get_session
41
+ if Threaded.get_session
42
+ raise Mongoid::Errors::InvalidSessionUse.new(:invalid_session_nesting)
43
+ end
42
44
  session = persistence_context.client.start_session(options)
43
45
  Threaded.set_session(session)
44
46
  yield(session)
45
47
  rescue Mongo::Error::InvalidSession => ex
46
- if ex.message == Mongo::Session::SESSIONS_NOT_SUPPORTED
48
+ if
49
+ # Driver 2.13.0+
50
+ defined?(Mongo::Error::SessionsNotSupported) &&
51
+ Mongo::Error::SessionsNotSupported === ex ||
52
+ # Legacy drivers
53
+ ex.message == Mongo::Session::SESSIONS_NOT_SUPPORTED
54
+ then
47
55
  raise Mongoid::Errors::InvalidSessionUse.new(:sessions_not_supported)
48
56
  end
49
57
  raise Mongoid::Errors::InvalidSessionUse.new(:invalid_session_use)
@@ -89,12 +97,20 @@ module Mongoid
89
97
  #
90
98
  # @since 6.4.0
91
99
  def with_session(options = {})
92
- raise Mongoid::Errors::InvalidSessionUse.new(:invalid_session_nesting) if Threaded.get_session
100
+ if Threaded.get_session
101
+ raise Mongoid::Errors::InvalidSessionUse.new(:invalid_session_nesting)
102
+ end
93
103
  session = persistence_context.client.start_session(options)
94
104
  Threaded.set_session(session)
95
105
  yield(session)
96
106
  rescue Mongo::Error::InvalidSession => ex
97
- if ex.message == Mongo::Session::SESSIONS_NOT_SUPPORTED
107
+ if
108
+ # Driver 2.13.0+
109
+ defined?(Mongo::Error::SessionsNotSupported) &&
110
+ Mongo::Error::SessionsNotSupported === ex ||
111
+ # Legacy drivers
112
+ ex.message == Mongo::Session::SESSIONS_NOT_SUPPORTED
113
+ then
98
114
  raise Mongoid::Errors::InvalidSessionUse.new(:sessions_not_supported)
99
115
  end
100
116
  raise Mongoid::Errors::InvalidSessionUse.new(:invalid_session_use)
@@ -435,7 +435,13 @@ module Mongoid
435
435
  #
436
436
  # @since 3.1.0
437
437
  def for_js(javascript, scope = {})
438
- js_query(BSON::CodeWithScope.new(javascript, scope))
438
+ code = if scope.empty?
439
+ # CodeWithScope is not supported for $where as of MongoDB 4.4
440
+ BSON::Code.new(javascript)
441
+ else
442
+ BSON::CodeWithScope.new(javascript, scope)
443
+ end
444
+ js_query(code)
439
445
  end
440
446
 
441
447
  private
@@ -72,7 +72,8 @@ module Mongoid
72
72
  # @since 5.1.0
73
73
  def create_with(attrs = {})
74
74
  tap do
75
- (@create_attrs ||= {}).merge!(attrs)
75
+ @create_attrs ||= {}
76
+ @create_attrs.update(attrs)
76
77
  end
77
78
  end
78
79
 
@@ -58,7 +58,7 @@ module Mongoid
58
58
  #
59
59
  # @since 1.0.0
60
60
  def __numeric__(object)
61
- object.to_s =~ /(^[-+]?[0-9]+$)|(\.0+$)|(\.$)/ ? object.to_i : Float(object)
61
+ object.to_s =~ /(\A[-+]?[0-9]+\z)|(\.0+\z)|(\.\z)/ ? object.to_i : Float(object)
62
62
  end
63
63
 
64
64
  # Evolve the object to an integer.
@@ -10,7 +10,7 @@ module Mongoid
10
10
  # Is the object a regexp?
11
11
  #
12
12
  # @example Is the object a regex?
13
- # /^[123]/.regexp?
13
+ # /\A[123]/.regexp?
14
14
  #
15
15
  # @return [ true ] Always true.
16
16
  #
@@ -22,7 +22,7 @@ module Mongoid
22
22
  # Evolve the object into a regex.
23
23
  #
24
24
  # @example Evolve the object to a regex.
25
- # Regexp.evolve("^[123]")
25
+ # Regexp.evolve("\A[123]")
26
26
  #
27
27
  # @param [ Regexp, String ] object The object to evolve.
28
28
  #
@@ -53,7 +53,7 @@ module Mongoid
53
53
  # Evolve the object into a raw bson regex.
54
54
  #
55
55
  # @example Evolve the object to a regex.
56
- # BSON::Regexp::Raw.evolve("^[123]")
56
+ # BSON::Regexp::Raw.evolve("\\A[123]")
57
57
  #
58
58
  # @param [ BSON::Regexp::Raw, String ] object The object to evolve.
59
59
  #
@@ -28,7 +28,7 @@ module Mongoid
28
28
  #
29
29
  # @since 1.0.0
30
30
  def __evolve_time__
31
- utc
31
+ getutc
32
32
  end
33
33
 
34
34
  module ClassMethods
@@ -7,6 +7,18 @@ module Mongoid
7
7
  # This module contains additional time with zone behaviour.
8
8
  module TimeWithZone
9
9
 
10
+ # Evolve the time as a date, UTC midnight.
11
+ #
12
+ # @example Evolve the time to a date query format.
13
+ # time.__evolve_date__
14
+ #
15
+ # @return [ Time ] The date at midnight UTC.
16
+ #
17
+ # @since 1.0.0
18
+ def __evolve_date__
19
+ ::Time.utc(year, month, day, 0, 0, 0, 0)
20
+ end
21
+
10
22
  # Evolve the time into a utc time.
11
23
  #
12
24
  # @example Evolve the time.
@@ -227,8 +227,9 @@ module Mongoid
227
227
  became = klass.new(clone_document)
228
228
  became._id = _id
229
229
  became.instance_variable_set(:@changed_attributes, changed_attributes)
230
- became.instance_variable_set(:@errors, ActiveModel::Errors.new(became))
231
- became.errors.instance_variable_set(:@messages, errors.instance_variable_get(:@messages))
230
+ new_errors = ActiveModel::Errors.new(became)
231
+ new_errors.copy!(errors)
232
+ became.instance_variable_set(:@errors, new_errors)
232
233
  became.instance_variable_set(:@new_record, new_record?)
233
234
  became.instance_variable_set(:@destroyed, destroyed?)
234
235
  became.changed_attributes["_type"] = self.class.to_s
@@ -46,9 +46,11 @@ module Mongoid
46
46
  value.each_pair do |_key, _value|
47
47
  value[_key] = (key == "$rename") ? _value.to_s : mongoize_for(key, klass, _key, _value)
48
48
  end
49
- (consolidated[key] ||= {}).merge!(value)
49
+ consolidated[key] ||= {}
50
+ consolidated[key].update(value)
50
51
  else
51
- (consolidated["$set"] ||= {}).merge!(key => mongoize_for(key, klass, key, value))
52
+ consolidated["$set"] ||= {}
53
+ consolidated["$set"].update(key => mongoize_for(key, klass, key, value))
52
54
  end
53
55
  end
54
56
  consolidated
@@ -9,7 +9,7 @@ module Mongoid
9
9
  # type.
10
10
  #
11
11
  # @example Mongoize the object.
12
- # Regexp.mongoize(/^[abc]/)
12
+ # Regexp.mongoize(/\A[abc]/)
13
13
  #
14
14
  # @param [ Regexp, String ] object The object to mongoize.
15
15
  #
@@ -498,7 +498,8 @@ module Mongoid
498
498
  def create_translations_getter(name, meth)
499
499
  generated_methods.module_eval do
500
500
  re_define_method("#{meth}_translations") do
501
- (attributes[name] ||= {}).with_indifferent_access
501
+ attributes[name] ||= {}
502
+ attributes[name].with_indifferent_access
502
503
  end
503
504
  alias_method :"#{meth}_t", :"#{meth}_translations"
504
505
  end
@@ -228,9 +228,11 @@ module Mongoid
228
228
  # document.halted_callback_hook(filter)
229
229
  #
230
230
  # @param [ Symbol ] filter The callback that halted.
231
+ # @param [ Symbol ] name The name of the callback that was halted
232
+ # (requires Rails 6.1+)
231
233
  #
232
234
  # @since 3.0.3
233
- def halted_callback_hook(filter)
235
+ def halted_callback_hook(filter, name = nil)
234
236
  @before_callback_halted = true
235
237
  end
236
238
 
@@ -7,8 +7,8 @@ module Mongoid
7
7
  # Does the supplied query match the attribute?
8
8
  #
9
9
  # @example Does this match?
10
- # matcher._matches?(/^Em/)
11
- # matcher._matches?(BSON::Regex::Raw.new("^Em"))
10
+ # matcher._matches?(/\AEm/)
11
+ # matcher._matches?(BSON::Regex::Raw.new("\\AEm"))
12
12
  #
13
13
  # @param [ BSON::Regexp::Raw, Regexp ] regexp The regular expression object.
14
14
  #
@@ -22,7 +22,13 @@ module Mongoid
22
22
  def add_to_set(adds)
23
23
  prepare_atomic_operation do |ops|
24
24
  process_atomic_operations(adds) do |field, value|
25
- existing = send(field) || (attributes[field] ||= [])
25
+ existing = send(field) || attributes[field]
26
+ if existing.nil?
27
+ attributes[field] = []
28
+ # Read the value out of attributes:
29
+ # https://jira.mongodb.org/browse/MONGOID-4874
30
+ existing = attributes[field]
31
+ end
26
32
  values = [ value ].flatten(1)
27
33
  values.each do |val|
28
34
  existing.push(val) unless existing.include?(val)
@@ -49,7 +55,10 @@ module Mongoid
49
55
  def push(pushes)
50
56
  prepare_atomic_operation do |ops|
51
57
  process_atomic_operations(pushes) do |field, value|
52
- existing = send(field) || (attributes[field] ||= [])
58
+ existing = send(field) || begin
59
+ attributes[field] ||= []
60
+ attributes[field]
61
+ end
53
62
  values = [ value ].flatten(1)
54
63
  values.each{ |val| existing.push(val) }
55
64
  ops[atomic_attribute_name(field)] = { "$each" => values }
@@ -116,6 +116,12 @@ module Mongoid
116
116
  client.with(client_options))
117
117
  end
118
118
 
119
+ def client_name
120
+ @client_name ||= options[:client] ||
121
+ Threaded.client_override ||
122
+ storage_options && __evaluate__(storage_options[:client])
123
+ end
124
+
119
125
  # Determine if this persistence context is equal to another.
120
126
  #
121
127
  # @example Compare two persistence contexts.
@@ -133,12 +139,6 @@ module Mongoid
133
139
 
134
140
  private
135
141
 
136
- def client_name
137
- @client_name ||= options[:client] ||
138
- Threaded.client_override ||
139
- storage_options && __evaluate__(storage_options[:client])
140
- end
141
-
142
142
  def set_options!(opts)
143
143
  @options ||= opts.each.reduce({}) do |_options, (key, value)|
144
144
  unless VALID_OPTIONS.include?(key.to_sym)
@@ -161,13 +161,13 @@ module Mongoid
161
161
  private
162
162
 
163
163
  def process(result)
164
- @remaining -= result.returned_count if limited?
165
- @cursor_id = result.cursor_id
166
- @coll_name ||= result.namespace.sub("#{database.name}.", '') if result.namespace
167
- documents = result.documents
164
+ documents = super
165
+
168
166
  if @cursor_id.zero? && !@after_first_batch
169
- (@cached_documents ||= []).concat(documents)
167
+ @cached_documents ||= []
168
+ @cached_documents.concat(documents)
170
169
  end
170
+
171
171
  @after_first_batch = true
172
172
  documents
173
173
  end
@@ -223,20 +223,40 @@ module Mongoid
223
223
  #
224
224
  # @since 5.0.0
225
225
  def each
226
- if system_collection? || !QueryCache.enabled?
226
+ if system_collection? || !QueryCache.enabled? || (respond_to?(:write?, true) && write?)
227
227
  super
228
228
  else
229
- unless cursor = cached_cursor
230
- read_with_retry do
231
- server = server_selector.select_server(cluster)
232
- cursor = CachedCursor.new(view, send_initial_query(server), server)
233
- QueryCache.cache_table[cache_key] = cursor
229
+ @cursor = nil
230
+ unless @cursor = cached_cursor
231
+
232
+ if driver_supports_cursor_sessions?
233
+ session = client.send(:get_session, @options)
234
+ read_with_retry(session, server_selector) do |server|
235
+ result = send_initial_query(server, session)
236
+ @cursor = get_cursor(result, server, session)
237
+ end
238
+ else
239
+ read_with_retry do
240
+ server = server_selector.select_server(cluster)
241
+ result = send_initial_query(server)
242
+ @cursor = get_cursor(result, server)
243
+ end
234
244
  end
235
245
  end
236
- cursor.each do |doc|
237
- yield doc
238
- end if block_given?
239
- cursor
246
+
247
+ if block_given?
248
+ if limit && limit != -1
249
+ @cursor.to_a[0...limit].each do |doc|
250
+ yield doc
251
+ end
252
+ else
253
+ @cursor.each do |doc|
254
+ yield doc
255
+ end
256
+ end
257
+ else
258
+ @cursor.to_enum
259
+ end
240
260
  end
241
261
  end
242
262
 
@@ -246,13 +266,30 @@ module Mongoid
246
266
  if limit
247
267
  key = [ collection.namespace, selector, nil, skip, sort, projection, collation ]
248
268
  cursor = QueryCache.cache_table[key]
249
- if cursor
250
- cursor.to_a[0...limit.abs]
251
- end
252
269
  end
253
270
  cursor || QueryCache.cache_table[cache_key]
254
271
  end
255
272
 
273
+ def get_cursor(result, server, session = nil)
274
+ if result.cursor_id == 0 || result.cursor_id.nil?
275
+ cursor = if session
276
+ CachedCursor.new(view, result, server, session: session)
277
+ else
278
+ CachedCursor.new(view, result, server)
279
+ end
280
+
281
+ QueryCache.cache_table[cache_key] = cursor
282
+ else
283
+ cursor = if session
284
+ Mongo::Cursor.new(view, result, server, session: session)
285
+ else
286
+ Mongo::Cursor.new(view, result, server)
287
+ end
288
+ end
289
+
290
+ cursor
291
+ end
292
+
256
293
  def cache_key
257
294
  [ collection.namespace, selector, limit, skip, sort, projection, collation ]
258
295
  end
@@ -260,6 +297,12 @@ module Mongoid
260
297
  def system_collection?
261
298
  collection.namespace =~ /\Asystem./
262
299
  end
300
+
301
+ def driver_supports_cursor_sessions?
302
+ # Driver versions 2.9 and newer support passing in a session to the
303
+ # cursor object.
304
+ (Mongo::VERSION.split('.').map(&:to_i) <=> [2, 9, 0]) > 0
305
+ end
263
306
  end
264
307
 
265
308
  # Adds behaviour to the query cache for collections.