mongoid 7.1.6 → 7.1.10

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 (71) 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 +31 -0
  6. data/lib/mongoid.rb +1 -0
  7. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +1 -1
  8. data/lib/mongoid/association/proxy.rb +1 -1
  9. data/lib/mongoid/association/referenced/has_many/enumerable.rb +1 -1
  10. data/lib/mongoid/association/referenced/has_many/proxy.rb +1 -1
  11. data/lib/mongoid/attributes.rb +8 -1
  12. data/lib/mongoid/criteria.rb +1 -1
  13. data/lib/mongoid/criteria/queryable/selector.rb +0 -4
  14. data/lib/mongoid/document.rb +3 -2
  15. data/lib/mongoid/errors/mongoid_error.rb +1 -1
  16. data/lib/mongoid/interceptable.rb +4 -2
  17. data/lib/mongoid/reloadable.rb +5 -0
  18. data/lib/mongoid/validatable/associated.rb +1 -1
  19. data/lib/mongoid/validatable/presence.rb +3 -3
  20. data/lib/mongoid/validatable/uniqueness.rb +1 -1
  21. data/lib/mongoid/version.rb +1 -1
  22. data/lib/rails/generators/mongoid/config/config_generator.rb +8 -1
  23. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +1 -1
  24. data/spec/app/models/address.rb +4 -0
  25. data/spec/app/models/customer.rb +11 -0
  26. data/spec/app/models/customer_address.rb +12 -0
  27. data/spec/app/models/dictionary.rb +6 -0
  28. data/spec/app/models/person.rb +9 -0
  29. data/spec/integration/app_spec.rb +178 -88
  30. data/spec/integration/callbacks_models.rb +49 -0
  31. data/spec/integration/callbacks_spec.rb +216 -0
  32. data/spec/integration/document_spec.rb +21 -0
  33. data/spec/lite_spec_helper.rb +6 -6
  34. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +50 -0
  35. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +17 -4
  36. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +17 -0
  37. data/spec/mongoid/atomic/paths_spec.rb +41 -0
  38. data/spec/mongoid/attributes_spec.rb +241 -0
  39. data/spec/mongoid/clients/options_spec.rb +2 -0
  40. data/spec/mongoid/contextual/atomic_spec.rb +17 -4
  41. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +36 -0
  42. data/spec/mongoid/criteria_spec.rb +4 -0
  43. data/spec/mongoid/document_query_spec.rb +51 -0
  44. data/spec/mongoid/errors/mongoid_error_spec.rb +20 -8
  45. data/spec/mongoid/factory_spec.rb +2 -2
  46. data/spec/mongoid/persistable/savable_spec.rb +4 -4
  47. data/spec/mongoid/persistable/settable_spec.rb +30 -0
  48. data/spec/mongoid/persistable_spec.rb +2 -2
  49. data/spec/shared/bin/get-mongodb-download-url +17 -0
  50. data/spec/shared/bin/s3-copy +45 -0
  51. data/spec/shared/bin/s3-upload +69 -0
  52. data/spec/shared/lib/mrss/cluster_config.rb +19 -4
  53. data/spec/shared/lib/mrss/constraints.rb +62 -6
  54. data/spec/shared/lib/mrss/docker_runner.rb +271 -0
  55. data/spec/shared/lib/mrss/lite_constraints.rb +16 -0
  56. data/spec/shared/lib/mrss/server_version_registry.rb +115 -0
  57. data/spec/shared/lib/mrss/spec_organizer.rb +32 -2
  58. data/spec/shared/lib/mrss/utils.rb +15 -0
  59. data/spec/shared/share/Dockerfile.erb +322 -0
  60. data/spec/shared/share/haproxy-1.conf +16 -0
  61. data/spec/shared/share/haproxy-2.conf +17 -0
  62. data/spec/shared/shlib/distro.sh +73 -0
  63. data/spec/shared/shlib/server.sh +317 -0
  64. data/spec/shared/shlib/set_env.sh +131 -0
  65. data/spec/spec_helper.rb +3 -1
  66. data/spec/support/constraints.rb +0 -226
  67. data/spec/support/spec_config.rb +8 -0
  68. metadata +542 -480
  69. metadata.gz.sig +0 -0
  70. data/spec/support/child_process_helper.rb +0 -76
  71. data/spec/support/lite_constraints.rb +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2dc047b0566d39e527a503400ca7bd624afcea9aebd7db795870333a795644c3
4
- data.tar.gz: 600c7431bf9a3464f24794c02807510f22b56d74a3981826cb1c6f2013a6c5e5
3
+ metadata.gz: 99b8d31638cfb3ff2cf789177ed38778cc7ed9281b2f90eb6790a53c4e817557
4
+ data.tar.gz: e4fccff34a4cc008ce1af7681cc6a5179960ab3dca7c8dada85ddbcef33d102d
5
5
  SHA512:
6
- metadata.gz: 6a430d43d0646baa0424f06471f4891330470d85dc23af4e2166779e36fa2e58cc44e1d645062290e8ec30dbad583dfc42f4d898b66ff5995422489e8868f577
7
- data.tar.gz: d35537d5127ff1840f4b8c920a446a22bee7bedcf675fe8212989798cc949d1d0e01c03e6df1b782def1956bbd4ecc81f1812d3b768e17029cd87e5e6583df96
6
+ metadata.gz: 1f9474eaa39877c8087d8f681a964a43943193ef43ec6e5fed05c349e9add56235e10b3959615213157514f7224e63157f90a96720bc993d15f0d2ea2112a7c3
7
+ data.tar.gz: 74db9f1912c3d4029c671f72f4856984f0a0520e3d1492f2ce8b1b9ce40cfd4efc2fe89923ac695c9644913533ca63e76842a993196cfb48b5c81c715e983d5c
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -17,7 +17,7 @@ Compatibility
17
17
 
18
18
  Mongoid supports and is tested against:
19
19
 
20
- - MRI 2.3-2.7
20
+ - MRI 2.3-3.0
21
21
  - JRuby 9.2
22
22
  - MongoDB server 2.6-4.4
23
23
 
data/Rakefile CHANGED
@@ -4,8 +4,13 @@ require "bundler"
4
4
  require "bundler/gem_tasks"
5
5
  Bundler.setup
6
6
 
7
+ ROOT = File.expand_path(File.join(File.dirname(__FILE__)))
8
+
9
+ $: << File.join(ROOT, 'spec/shared/lib')
10
+
7
11
  require "rake"
8
12
  require "rspec/core/rake_task"
13
+ require 'mrss/spec_organizer'
9
14
 
10
15
  $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
11
16
  require "mongoid/version"
@@ -35,6 +40,32 @@ RSpec::Core::RakeTask.new('spec:progress') do |spec|
35
40
  spec.pattern = "spec/**/*_spec.rb"
36
41
  end
37
42
 
43
+ CLASSIFIERS = [
44
+ [%r,^mongoid/attribute,, :attributes],
45
+ [%r,^mongoid/association/[or],, :associations_referenced],
46
+ [%r,^mongoid/association,, :associations],
47
+ [%r,^mongoid,, :unit],
48
+ [%r,^integration,, :integration],
49
+ [%r,^rails,, :rails],
50
+ ]
51
+
52
+ RUN_PRIORITY = %i(
53
+ unit attributes associations_referenced associations
54
+ integration rails
55
+ )
56
+
57
+ def spec_organizer
58
+ Mrss::SpecOrganizer.new(
59
+ root: ROOT,
60
+ classifiers: CLASSIFIERS,
61
+ priority_order: RUN_PRIORITY,
62
+ )
63
+ end
64
+
65
+ task :ci do
66
+ spec_organizer.run
67
+ end
68
+
38
69
  task :default => :spec
39
70
 
40
71
  desc "Generate all documentation"
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"
@@ -415,7 +415,7 @@ module Mongoid
415
415
  # @param [ Proc ] block Optional block to pass.
416
416
  #
417
417
  # @return [ Criteria, Object ] A Criteria or return value from the target.
418
- def method_missing(name, *args, &block)
418
+ ruby2_keywords def method_missing(name, *args, &block)
419
419
  return super if _target.respond_to?(name)
420
420
  klass.send(:with_scope, criteria) do
421
421
  criteria.public_send(name, *args, &block)
@@ -133,7 +133,7 @@ module Mongoid
133
133
  # @param [ String, Symbol ] name The name of the method.
134
134
  # @param [ Array ] args The arguments passed to the method.
135
135
  #
136
- def method_missing(name, *args, &block)
136
+ ruby2_keywords def method_missing(name, *args, &block)
137
137
  _target.send(name, *args, &block)
138
138
  end
139
139
 
@@ -498,7 +498,7 @@ module Mongoid
498
498
  end
499
499
  end
500
500
 
501
- def method_missing(name, *args, &block)
501
+ ruby2_keywords def method_missing(name, *args, &block)
502
502
  entries.send(name, *args, &block)
503
503
  end
504
504
 
@@ -436,7 +436,7 @@ module Mongoid
436
436
  # @return [ Criteria, Object ] A Criteria or return value from the target.
437
437
  #
438
438
  # @since 2.0.0.beta.1
439
- def method_missing(name, *args, &block)
439
+ ruby2_keywords def method_missing(name, *args, &block)
440
440
  if _target.respond_to?(name)
441
441
  _target.send(name, *args, &block)
442
442
  else
@@ -160,6 +160,11 @@ module Mongoid
160
160
  # @since 1.0.0
161
161
  def write_attribute(name, value)
162
162
  field_name = database_field_name(name)
163
+
164
+ if attribute_missing?(field_name)
165
+ raise ActiveModel::MissingAttributeError, "Missing attribute: '#{name}'"
166
+ end
167
+
163
168
  if attribute_writable?(field_name)
164
169
  _assigning do
165
170
  validate_attribute_value(field_name, value)
@@ -177,6 +182,8 @@ module Mongoid
177
182
  end
178
183
  typed_value
179
184
  end
185
+ else
186
+ # TODO: MONGOID-5072
180
187
  end
181
188
  end
182
189
  alias :[]= :write_attribute
@@ -294,7 +301,7 @@ module Mongoid
294
301
  def read_raw_attribute(name)
295
302
  normalized = database_field_name(name.to_s)
296
303
  if attribute_missing?(normalized)
297
- raise ActiveModel::MissingAttributeError, "Missing attribute: '#{name}'."
304
+ raise ActiveModel::MissingAttributeError, "Missing attribute: '#{name}'"
298
305
  end
299
306
  if hash_dot_syntax?(normalized)
300
307
  attributes.__nested__(normalized)
@@ -518,7 +518,7 @@ module Mongoid
518
518
  # @return [ Object ] The result of the method call.
519
519
  #
520
520
  # @since 1.0.0
521
- def method_missing(name, *args, &block)
521
+ ruby2_keywords def method_missing(name, *args, &block)
522
522
  if klass.respond_to?(name)
523
523
  klass.send(:with_scope, self) do
524
524
  klass.send(name, *args, &block)
@@ -123,10 +123,6 @@ module Mongoid
123
123
  # {'foo' => {'$lt' => 5}}. This step should be done after all
124
124
  # value-based processing is complete.
125
125
  if key.is_a?(Key)
126
- if serializer && evolved_value != value
127
- raise NotImplementedError, "This method is not prepared to handle key being a Key and serializer being not nil"
128
- end
129
-
130
126
  evolved_value = key.transform_value(evolved_value)
131
127
  end
132
128
 
@@ -229,8 +229,9 @@ module Mongoid
229
229
  became = klass.new(clone_document)
230
230
  became._id = _id
231
231
  became.instance_variable_set(:@changed_attributes, changed_attributes)
232
- became.instance_variable_set(:@errors, ActiveModel::Errors.new(became))
233
- became.errors.instance_variable_set(:@messages, errors.instance_variable_get(:@messages))
232
+ new_errors = ActiveModel::Errors.new(became)
233
+ new_errors.copy!(errors)
234
+ became.instance_variable_set(:@errors, new_errors)
234
235
  became.instance_variable_set(:@new_record, new_record?)
235
236
  became.instance_variable_set(:@destroyed, destroyed?)
236
237
  became.changed_attributes["_type"] = self.class.to_s
@@ -48,7 +48,7 @@ module Mongoid
48
48
  #
49
49
  # @return [ String ] A localized error message string.
50
50
  def translate(key, options)
51
- ::I18n.translate("#{BASE_KEY}.#{key}", options)
51
+ ::I18n.translate("#{BASE_KEY}.#{key}", **options)
52
52
  end
53
53
 
54
54
  # Create the problem.
@@ -125,7 +125,7 @@ module Mongoid
125
125
  # @return [ Document ] The document
126
126
  #
127
127
  # @since 2.3.0
128
- def run_callbacks(kind, *args, &block)
128
+ ruby2_keywords def run_callbacks(kind, *args, &block)
129
129
  cascadable_children(kind).each do |child|
130
130
  if child.run_callbacks(child_callback_type(kind, child), *args) == false
131
131
  return false
@@ -234,9 +234,11 @@ module Mongoid
234
234
  # document.halted_callback_hook(filter)
235
235
  #
236
236
  # @param [ Symbol ] filter The callback that halted.
237
+ # @param [ Symbol ] name The name of the callback that was halted
238
+ # (requires Rails 6.1+)
237
239
  #
238
240
  # @since 3.0.3
239
- def halted_callback_hook(filter)
241
+ def halted_callback_hook(filter, name = nil)
240
242
  @before_callback_halted = true
241
243
  end
242
244
 
@@ -21,6 +21,11 @@ module Mongoid
21
21
  #
22
22
  # @since 1.0.0
23
23
  def reload
24
+ if @atomic_selector
25
+ # Clear atomic_selector cache for sharded clusters. MONGOID-5076
26
+ remove_instance_variable('@atomic_selector')
27
+ end
28
+
24
29
  reloaded = _reload
25
30
  if Mongoid.raise_not_found_error && reloaded.empty?
26
31
  raise Errors::DocumentNotFound.new(self.class, _id, _id)
@@ -43,7 +43,7 @@ module Mongoid
43
43
  ensure
44
44
  document.exit_validate
45
45
  end
46
- document.errors.add(attribute, :invalid, options) unless valid
46
+ document.errors.add(attribute, :invalid, **options) unless valid
47
47
  end
48
48
  end
49
49
  end
@@ -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
 
@@ -2,5 +2,5 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  module Mongoid
5
- VERSION = "7.1.6"
5
+ VERSION = "7.1.10"
6
6
  end
@@ -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,11 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ class Customer
5
+ include Mongoid::Document
6
+
7
+ field :name
8
+
9
+ embeds_one :home_address, class_name: 'CustomerAddress', as: :addressable
10
+ embeds_one :work_address, class_name: 'CustomerAddress', as: :addressable
11
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ class CustomerAddress
5
+ include Mongoid::Document
6
+
7
+ field :street, type: String
8
+ field :city, type: String
9
+ field :state, type: String
10
+
11
+ embedded_in :addressable, polymorphic: true
12
+ end
@@ -6,7 +6,13 @@ class Dictionary
6
6
  field :name, type: String
7
7
  field :publisher, type: String
8
8
  field :year, type: Integer
9
+
10
+ # This field must be a Time
9
11
  field :published, type: Time
12
+
13
+ # This field must be a Date
14
+ field :submitted_on, type: Date
15
+
10
16
  field :description, type: String, localize: true
11
17
  field :l, type: String, as: :language
12
18
  has_many :words, validate: false
@@ -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(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
@@ -181,11 +204,44 @@ describe 'Mongoid application tests' do
181
204
  end
182
205
  end
183
206
 
207
+ def parse_mongodb_uri(uri)
208
+ pre, query = uri.split('?', 2)
209
+ if pre =~ %r,\A(mongodb(?:.*?))://([^/]+)(?:/(.*))?\z,
210
+ protocol = $1
211
+ hosts = $2
212
+ database = $3
213
+ if database == ''
214
+ database = nil
215
+ end
216
+ else
217
+ raise ArgumentError, "Invalid MongoDB URI: #{uri}"
218
+ end
219
+ if query == ''
220
+ query = nil
221
+ end
222
+ {
223
+ protocol: protocol,
224
+ hosts: hosts,
225
+ database: database,
226
+ query: query,
227
+ }
228
+ end
229
+
230
+ def build_mongodb_uri(parts)
231
+ "#{parts.fetch(:protocol)}://#{parts.fetch(:hosts)}/#{parts[:database]}?#{parts[:query]}"
232
+ end
233
+
184
234
  def write_mongoid_yml
235
+ # HACK: the driver does not provide a MongoDB URI parser and assembler,
236
+ # and the Ruby standard library URI module doesn't handle multiple hosts.
237
+ parts = parse_mongodb_uri(SpecConfig.instance.uri_str)
238
+ parts[:database] = 'mongoid_test'
239
+ uri = build_mongodb_uri(parts)
240
+ p uri
185
241
  env_config = {'clients' => {'default' => {
186
242
  # TODO massive hack, will fail if uri specifies a database name or
187
243
  # any uri options
188
- 'uri' => "#{SpecConfig.instance.uri_str}/mongoid_test",
244
+ 'uri' => uri,
189
245
  }}}
190
246
  config = {'development' => env_config, 'production' => env_config}
191
247
  File.open('config/mongoid.yml', 'w') do |f|
@@ -193,7 +249,7 @@ describe 'Mongoid application tests' do
193
249
  end
194
250
  end
195
251
 
196
- def adjust_app_gemfile(rails_version: nil)
252
+ def adjust_app_gemfile(rails_version: SpecConfig.instance.rails_version)
197
253
  remove_bundler_req
198
254
 
199
255
  gemfile_lines = IO.readlines('Gemfile')
@@ -205,14 +261,45 @@ describe 'Mongoid application tests' do
205
261
  gemfile_lines.delete_if do |line|
206
262
  line =~ /rails/
207
263
  end
208
- 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
209
269
  end
210
270
  File.open('Gemfile', 'w') do |f|
211
271
  f << gemfile_lines.join
212
272
  end
213
273
  end
214
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
+
215
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.
216
303
  lock_lines = IO.readlines('Gemfile.lock')
217
304
  # Get rid of the bundled with line so that whatever bundler is installed
218
305
  # on the system is usable with the application.
@@ -230,14 +317,14 @@ describe 'Mongoid application tests' do
230
317
  # in `initialize': too long unix socket path (126bytes given but 108bytes max) (ArgumentError)
231
318
  # Is it trying to create unix sockets in current directory?
232
319
  # https://stackoverflow.com/questions/30302021/rails-runner-without-spring
233
- 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)
234
321
  end
235
322
 
236
323
  def clean_env
237
324
  @clean_env ||= Hash[ENV.keys.grep(/BUNDLE|RUBYOPT/).map { |k| [k, nil ] }]
238
325
  end
239
326
 
240
- def wait_for_port(port, timeout)
327
+ def wait_for_port(port, timeout, process)
241
328
  deadline = Time.now + timeout
242
329
  loop do
243
330
  begin
@@ -245,6 +332,9 @@ describe 'Mongoid application tests' do
245
332
  return
246
333
  end
247
334
  rescue IOError, SystemCallError
335
+ unless process.alive?
336
+ raise "Process #{process} died while waiting for port #{port}"
337
+ end
248
338
  if Time.now > deadline
249
339
  raise
250
340
  end