mongoid 7.1.7 → 7.1.11

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 (81) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +1 -1
  4. data/Rakefile +31 -0
  5. data/lib/config/locales/en.yml +13 -0
  6. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +1 -1
  7. data/lib/mongoid/association/proxy.rb +1 -1
  8. data/lib/mongoid/association/referenced/has_many/enumerable.rb +1 -1
  9. data/lib/mongoid/association/referenced/has_many/proxy.rb +1 -1
  10. data/lib/mongoid/attributes.rb +8 -1
  11. data/lib/mongoid/config/environment.rb +9 -1
  12. data/lib/mongoid/contextual/atomic.rb +7 -2
  13. data/lib/mongoid/contextual/none.rb +3 -0
  14. data/lib/mongoid/criteria/queryable/selectable.rb +2 -2
  15. data/lib/mongoid/criteria/queryable/storable.rb +4 -4
  16. data/lib/mongoid/criteria.rb +1 -1
  17. data/lib/mongoid/document.rb +3 -2
  18. data/lib/mongoid/errors/empty_config_file.rb +26 -0
  19. data/lib/mongoid/errors/invalid_config_file.rb +26 -0
  20. data/lib/mongoid/errors/mongoid_error.rb +1 -1
  21. data/lib/mongoid/errors.rb +2 -0
  22. data/lib/mongoid/interceptable.rb +1 -1
  23. data/lib/mongoid/persistence_context.rb +3 -1
  24. data/lib/mongoid/reloadable.rb +5 -0
  25. data/lib/mongoid/tasks/database.rb +1 -1
  26. data/lib/mongoid/validatable/associated.rb +1 -1
  27. data/lib/mongoid/validatable/presence.rb +3 -3
  28. data/lib/mongoid/validatable/uniqueness.rb +1 -1
  29. data/lib/mongoid/version.rb +1 -1
  30. data/lib/mongoid.rb +1 -0
  31. data/lib/rails/generators/mongoid/config/config_generator.rb +8 -1
  32. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +1 -1
  33. data/spec/app/models/address.rb +4 -0
  34. data/spec/app/models/mop.rb +26 -0
  35. data/spec/app/models/person.rb +9 -0
  36. data/spec/integration/app_spec.rb +144 -87
  37. data/spec/integration/contextual/empty_spec.rb +142 -0
  38. data/spec/integration/document_spec.rb +21 -0
  39. data/spec/lite_spec_helper.rb +5 -5
  40. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +17 -4
  41. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +17 -0
  42. data/spec/mongoid/attributes_spec.rb +241 -0
  43. data/spec/mongoid/clients/factory_spec.rb +11 -0
  44. data/spec/mongoid/clients/options_spec.rb +11 -3
  45. data/spec/mongoid/config/environment_spec.rb +86 -8
  46. data/spec/mongoid/contextual/atomic_spec.rb +81 -29
  47. data/spec/mongoid/contextual/geo_near_spec.rb +1 -1
  48. data/spec/mongoid/criteria_spec.rb +4 -0
  49. data/spec/mongoid/document_query_spec.rb +51 -0
  50. data/spec/mongoid/document_spec.rb +21 -1
  51. data/spec/mongoid/errors/invalid_config_file_spec.rb +32 -0
  52. data/spec/mongoid/errors/mongoid_error_spec.rb +20 -8
  53. data/spec/mongoid/factory_spec.rb +2 -2
  54. data/spec/mongoid/persistable/savable_spec.rb +4 -4
  55. data/spec/mongoid/persistable/settable_spec.rb +30 -0
  56. data/spec/mongoid/persistable/updatable_spec.rb +2 -0
  57. data/spec/mongoid/persistable_spec.rb +2 -2
  58. data/spec/shared/bin/get-mongodb-download-url +17 -0
  59. data/spec/shared/bin/s3-copy +45 -0
  60. data/spec/shared/bin/s3-upload +69 -0
  61. data/spec/shared/lib/mrss/cluster_config.rb +19 -4
  62. data/spec/shared/lib/mrss/constraints.rb +67 -12
  63. data/spec/shared/lib/mrss/docker_runner.rb +10 -1
  64. data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
  65. data/spec/shared/lib/mrss/lite_constraints.rb +16 -0
  66. data/spec/shared/lib/mrss/server_version_registry.rb +84 -33
  67. data/spec/shared/lib/mrss/spec_organizer.rb +32 -2
  68. data/spec/shared/lib/mrss/utils.rb +15 -0
  69. data/spec/shared/share/Dockerfile.erb +126 -32
  70. data/spec/shared/share/haproxy-1.conf +16 -0
  71. data/spec/shared/share/haproxy-2.conf +17 -0
  72. data/spec/shared/shlib/server.sh +123 -26
  73. data/spec/shared/shlib/set_env.sh +4 -1
  74. data/spec/spec_helper.rb +3 -1
  75. data/spec/support/constraints.rb +0 -226
  76. data/spec/support/spec_config.rb +8 -0
  77. data.tar.gz.sig +0 -0
  78. metadata +555 -503
  79. metadata.gz.sig +0 -0
  80. data/spec/support/child_process_helper.rb +0 -76
  81. data/spec/support/lite_constraints.rb +0 -22
@@ -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
 
@@ -2,5 +2,5 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  module Mongoid
5
- VERSION = "7.1.7"
5
+ VERSION = "7.1.11"
6
6
  end
data/lib/mongoid.rb CHANGED
@@ -6,6 +6,7 @@ require "support/ruby_version"
6
6
  require "forwardable"
7
7
  require "time"
8
8
  require "set"
9
+ require "ruby2_keywords"
9
10
 
10
11
  require "active_support"
11
12
  require "active_support/core_ext"
@@ -15,7 +15,14 @@ module Mongoid
15
15
  end
16
16
 
17
17
  def app_name
18
- Rails::Application.subclasses.first.parent.to_s.underscore
18
+ app_cls = Rails.application.class
19
+ parent = begin
20
+ # Rails 6.1+
21
+ app_cls.module_parent_name
22
+ rescue NoMethodError
23
+ app_cls.parent.to_s
24
+ end
25
+ parent.underscore
19
26
  end
20
27
 
21
28
  def create_config_file
@@ -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 ismaster commands. (default: 10)
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)
@@ -78,5 +78,9 @@ class Address
78
78
  def streets
79
79
  all.map(&:street)
80
80
  end
81
+
82
+ def city_and_state(city:, state:)
83
+ where(city: city, state: state)
84
+ end
81
85
  end
82
86
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ # This class is used for embedded matcher testing.
5
+ class Mop
6
+ include Mongoid::Document
7
+
8
+ # The dynamic attributes are used so that the tests can use various
9
+ # field names as makes sense for the particular operator.
10
+ include Mongoid::Attributes::Dynamic
11
+
12
+ # We need some fields of specific types because the query conditions are
13
+ # transformed differently based on the type of field being queried.
14
+ field :int_field, type: Integer
15
+ field :array_field, type: Array
16
+ field :date_field, type: Date
17
+ field :time_field, type: Time
18
+ field :datetime_field, type: DateTime
19
+ field :big_decimal_field, type: BigDecimal
20
+ field :decimal128_field, type: BSON::Decimal128
21
+ field :symbol_field, type: Symbol
22
+ field :bson_symbol_field, type: BSON::Symbol::Raw
23
+ field :regexp_field, type: Regexp
24
+ field :bson_regexp_field, type: BSON::Regexp::Raw
25
+ end
26
+
@@ -136,6 +136,10 @@ class Person
136
136
  scope :without_ssn, ->{ without(:ssn) }
137
137
  scope :search, ->(query){ any_of({ title: query }) }
138
138
 
139
+ def self.older_than(age:)
140
+ where(:age.gt => age)
141
+ end
142
+
139
143
  def score_with_rescoring=(score)
140
144
  @rescored = score.to_i + 20
141
145
  self.score_without_rescoring = score
@@ -206,6 +210,11 @@ class Person
206
210
  self.map_with_default["key"] = value
207
211
  end
208
212
 
213
+ def set_personal_data(ssn:, age:)
214
+ self.ssn = ssn
215
+ self.age = age
216
+ end
217
+
209
218
  reset_callbacks(:validate)
210
219
  reset_callbacks(:create)
211
220
  reset_callbacks(:save)
@@ -13,109 +13,131 @@ describe 'Mongoid application tests' do
13
13
  end
14
14
 
15
15
  require 'fileutils'
16
- require 'support/child_process_helper'
16
+ require 'mrss/child_process_helper'
17
17
  require 'open-uri'
18
18
 
19
19
  FileUtils.mkdir_p(TMP_BASE)
20
20
  end
21
21
 
22
- context 'demo application - sinatra' do
23
- it 'runs' do
24
- clone_application(
25
- 'https://github.com/mongoid/mongoid-demo',
26
- subdir: 'sinatra-minimal',
27
- ) do
22
+ context 'demo application' do
23
+ context 'sinatra' do
24
+ it 'runs' do
25
+ clone_application(
26
+ 'https://github.com/mongoid/mongoid-demo',
27
+ subdir: 'sinatra-minimal',
28
+ ) do
28
29
 
29
- process = ChildProcess.build(*%w(bundle exec ruby app.rb))
30
- process.environment.update(clean_env)
31
- process.io.inherit!
32
- process.start
33
-
34
- begin
35
30
  # JRuby needs a long timeout
36
- wait_for_port(4567, 20)
37
- sleep 1
38
-
39
- uri = URI.parse('http://localhost:4567/posts')
40
- resp = JSON.parse(uri.open.read)
41
- ensure
42
- Process.kill('TERM', process.pid)
43
- status = process.wait
44
- end
31
+ start_app(%w(bundle exec ruby app.rb), 4567, 40) do |port|
32
+ uri = URI.parse('http://localhost:4567/posts')
33
+ resp = JSON.parse(uri.open.read)
45
34
 
46
- resp.should == []
35
+ resp.should == []
47
36
 
48
- status.should == 0
37
+ end
38
+ end
49
39
  end
50
40
  end
51
- end
52
41
 
53
- context 'demo application - rails-api' do
54
- ['~> 6.0.0'].each do |rails_version|
55
- context "with rails #{rails_version}" do
56
- it 'runs' do
57
- clone_application(
58
- 'https://github.com/mongoid/mongoid-demo',
59
- subdir: 'rails-api',
60
- rails_version: rails_version,
61
- ) do
62
-
63
- process = ChildProcess.build(*%w(bundle exec rails s))
64
- process.environment.update(clean_env)
65
- process.io.inherit!
66
- process.start
67
-
68
- begin
69
- # JRuby needs a long timeout
70
- wait_for_port(3000, 30)
71
- sleep 1
72
-
73
- uri = URI.parse('http://localhost:3000/posts')
74
- resp = JSON.parse(uri.open.read)
75
- ensure
76
- Process.kill('TERM', process.pid)
77
- status = process.wait
78
- end
42
+ context 'rails-api' do
43
+ it 'runs' do
44
+ clone_application(
45
+ 'https://github.com/mongoid/mongoid-demo',
46
+ subdir: 'rails-api',
47
+ ) do
79
48
 
80
- resp.should == []
49
+ # JRuby needs a long timeout
50
+ start_app(%w(bundle exec rails s), 3000, 50) do |port|
51
+ uri = URI.parse('http://localhost:3000/posts')
52
+ resp = JSON.parse(uri.open.read)
81
53
 
82
- # 143 = 128 + 15
83
- [0, 15, 143].should include(status)
54
+ resp.should == []
84
55
  end
85
56
  end
86
57
  end
87
58
  end
88
59
  end
89
60
 
61
+ def start_app(cmd, port, timeout)
62
+ process = ChildProcess.build(*cmd)
63
+ process.environment.update(clean_env)
64
+ process.io.inherit!
65
+ process.start
66
+
67
+ begin
68
+ wait_for_port(port, timeout, process)
69
+ sleep 1
70
+
71
+ rv = yield port
72
+ ensure
73
+ # The process may have already died (due to an error exit) -
74
+ # in this case killing it will raise an exception.
75
+ Process.kill('TERM', process.pid) rescue nil
76
+ status = process.wait
77
+ end
78
+
79
+ # Exit should be either success or SIGTERM
80
+ [0, 15, 128 + 15].should include(status)
81
+
82
+ rv
83
+ end
84
+
90
85
  context 'new application - rails' do
91
- ['~> 5.1.0', '~> 5.2.0', '~> 6.0.0'].each do |rails_version|
92
- context "with rails #{rails_version}" do
93
- it 'creates' do
94
- ChildProcessHelper.check_call(%w(gem uni rails -a))
95
- ChildProcessHelper.check_call(%w(gem install rails --no-document -v) + [rails_version])
96
-
97
- Dir.chdir(TMP_BASE) do
98
- FileUtils.rm_rf('mongoid-test')
99
- ChildProcessHelper.check_call(%w(rails new mongoid-test --skip-spring --skip-active-record), env: clean_env)
100
-
101
- Dir.chdir('mongoid-test') do
102
- adjust_app_gemfile
103
- ChildProcessHelper.check_call(%w(bundle install), env: clean_env)
104
-
105
- ChildProcessHelper.check_call(%w(rails g model post), env: clean_env)
106
- ChildProcessHelper.check_call(%w(rails g model comment post:belongs_to), env: clean_env)
107
-
108
- # https://jira.mongodb.org/browse/MONGOID-4885
109
- comment_text = File.read('app/models/comment.rb')
110
- comment_text.should =~ /belongs_to :post/
111
- comment_text.should_not =~ /embedded_in :post/
112
- end
113
- end
86
+ it 'creates' do
87
+ install_rails
88
+
89
+ Dir.chdir(TMP_BASE) do
90
+ FileUtils.rm_rf('mongoid-test')
91
+ Mrss::ChildProcessHelper.check_call(%w(rails new mongoid-test --skip-spring --skip-active-record), env: clean_env)
92
+
93
+ Dir.chdir('mongoid-test') do
94
+ adjust_app_gemfile
95
+ Mrss::ChildProcessHelper.check_call(%w(bundle install), env: clean_env)
96
+
97
+ Mrss::ChildProcessHelper.check_call(%w(rails g model post), env: clean_env)
98
+ Mrss::ChildProcessHelper.check_call(%w(rails g model comment post:belongs_to), env: clean_env)
99
+
100
+ # https://jira.mongodb.org/browse/MONGOID-4885
101
+ comment_text = File.read('app/models/comment.rb')
102
+ comment_text.should =~ /belongs_to :post/
103
+ comment_text.should_not =~ /embedded_in :post/
104
+ end
105
+ end
106
+ end
107
+
108
+ it 'generates Mongoid config' do
109
+ install_rails
110
+
111
+ Dir.chdir(TMP_BASE) do
112
+ FileUtils.rm_rf('mongoid-test-config')
113
+ Mrss::ChildProcessHelper.check_call(%w(rails new mongoid-test-config --skip-spring --skip-active-record), env: clean_env)
114
+
115
+ Dir.chdir('mongoid-test-config') do
116
+ adjust_app_gemfile
117
+ Mrss::ChildProcessHelper.check_call(%w(bundle install), env: clean_env)
118
+
119
+ mongoid_config_file = File.join(TMP_BASE,'mongoid-test-config/config/mongoid.yml')
120
+
121
+ File.exist?(mongoid_config_file).should be false
122
+ Mrss::ChildProcessHelper.check_call(%w(rails g mongoid:config), env: clean_env)
123
+ File.exist?(mongoid_config_file).should be true
124
+
125
+ config_text = File.read(mongoid_config_file)
126
+ config_text.should =~ /mongoid_test_config_development/
127
+ config_text.should =~ /mongoid_test_config_test/
114
128
  end
115
129
  end
116
130
  end
117
131
  end
118
132
 
133
+ def install_rails
134
+ Mrss::ChildProcessHelper.check_call(%w(gem uni rails -a))
135
+ if (rails_version = SpecConfig.instance.rails_version) == 'master'
136
+ else
137
+ Mrss::ChildProcessHelper.check_call(%w(gem install rails --no-document -v) + [rails_version])
138
+ end
139
+ end
140
+
119
141
  context 'local test applications' do
120
142
  let(:client) { Mongoid.default_client }
121
143
 
@@ -136,7 +158,7 @@ describe 'Mongoid application tests' do
136
158
  before do
137
159
  Dir.chdir(APP_PATH) do
138
160
  remove_bundler_req
139
- ChildProcessHelper.check_call(%w(bundle install), env: env)
161
+ Mrss::ChildProcessHelper.check_call(%w(bundle install), env: env)
140
162
  write_mongoid_yml
141
163
  end
142
164
 
@@ -150,7 +172,7 @@ describe 'Mongoid application tests' do
150
172
  end
151
173
  index.should be nil
152
174
 
153
- ChildProcessHelper.check_call(%w(bundle exec rake db:mongoid:create_indexes),
175
+ Mrss::ChildProcessHelper.check_call(%w(bundle exec rake db:mongoid:create_indexes),
154
176
  cwd: APP_PATH, env: env)
155
177
 
156
178
  index = client['posts'].indexes.detect do |index|
@@ -165,13 +187,14 @@ describe 'Mongoid application tests' do
165
187
  end
166
188
  end
167
189
 
168
- def clone_application(repo_url, subdir: nil, rails_version: nil)
190
+ def clone_application(repo_url, subdir: nil)
169
191
  Dir.chdir(TMP_BASE) do
170
192
  FileUtils.rm_rf(File.basename(repo_url))
171
- ChildProcessHelper.check_call(%w(git clone) + [repo_url])
193
+ Mrss::ChildProcessHelper.check_call(%w(git clone) + [repo_url])
172
194
  Dir.chdir(File.join(*[File.basename(repo_url), subdir].compact)) do
173
- adjust_app_gemfile(rails_version: rails_version)
174
- ChildProcessHelper.check_call(%w(bundle install), env: clean_env)
195
+ adjust_app_gemfile
196
+ adjust_rails_defaults
197
+ Mrss::ChildProcessHelper.check_call(%w(bundle install), env: clean_env)
175
198
  puts `git diff`
176
199
 
177
200
  write_mongoid_yml
@@ -226,7 +249,7 @@ describe 'Mongoid application tests' do
226
249
  end
227
250
  end
228
251
 
229
- def adjust_app_gemfile(rails_version: nil)
252
+ def adjust_app_gemfile(rails_version: SpecConfig.instance.rails_version)
230
253
  remove_bundler_req
231
254
 
232
255
  gemfile_lines = IO.readlines('Gemfile')
@@ -238,14 +261,45 @@ describe 'Mongoid application tests' do
238
261
  gemfile_lines.delete_if do |line|
239
262
  line =~ /rails/
240
263
  end
241
- gemfile_lines << "gem 'rails', '#{rails_version}'\n"
264
+ if rails_version == 'master'
265
+ gemfile_lines << "gem 'rails', git: 'https://github.com/rails/rails'\n"
266
+ else
267
+ gemfile_lines << "gem 'rails', '~> #{rails_version}.0'\n"
268
+ end
242
269
  end
243
270
  File.open('Gemfile', 'w') do |f|
244
271
  f << gemfile_lines.join
245
272
  end
246
273
  end
247
274
 
275
+ def adjust_rails_defaults(rails_version: SpecConfig.instance.rails_version)
276
+ if File.exist?('config/application.rb')
277
+ lines = IO.readlines('config/application.rb')
278
+ lines.each do |line|
279
+ line.gsub!(/config.load_defaults \d\.\d/, "config.load_defaults #{rails_version}")
280
+ end
281
+ File.open('config/application.rb', 'w') do |f|
282
+ f << lines.join
283
+ end
284
+ end
285
+
286
+ if rails_version == '5.1'
287
+ secrets = {
288
+ 'development' => {
289
+ 'secret_key_base' => 'abracadabra',
290
+ 'my_secret_token' => 'very_secret',
291
+ },
292
+ }
293
+ File.open('config/secrets.yml', 'w') do |f|
294
+ f << YAML.dump(secrets)
295
+ end
296
+ end
297
+ end
298
+
248
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.
249
303
  lock_lines = IO.readlines('Gemfile.lock')
250
304
  # Get rid of the bundled with line so that whatever bundler is installed
251
305
  # on the system is usable with the application.
@@ -263,14 +317,14 @@ describe 'Mongoid application tests' do
263
317
  # in `initialize': too long unix socket path (126bytes given but 108bytes max) (ArgumentError)
264
318
  # Is it trying to create unix sockets in current directory?
265
319
  # https://stackoverflow.com/questions/30302021/rails-runner-without-spring
266
- ChildProcessHelper.check_call(%w(bin/spring binstub --remove --all), env: clean_env)
320
+ Mrss::ChildProcessHelper.check_call(%w(bin/spring binstub --remove --all), env: clean_env)
267
321
  end
268
322
 
269
323
  def clean_env
270
324
  @clean_env ||= Hash[ENV.keys.grep(/BUNDLE|RUBYOPT/).map { |k| [k, nil ] }]
271
325
  end
272
326
 
273
- def wait_for_port(port, timeout)
327
+ def wait_for_port(port, timeout, process)
274
328
  deadline = Time.now + timeout
275
329
  loop do
276
330
  begin
@@ -278,6 +332,9 @@ describe 'Mongoid application tests' do
278
332
  return
279
333
  end
280
334
  rescue IOError, SystemCallError
335
+ unless process.alive?
336
+ raise "Process #{process} died while waiting for port #{port}"
337
+ end
281
338
  if Time.now > deadline
282
339
  raise
283
340
  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