mongoid 7.2.0 → 7.3.0

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 (191) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/Rakefile +16 -0
  4. data/lib/config/locales/en.yml +2 -2
  5. data/lib/mongoid/association/accessors.rb +1 -1
  6. data/lib/mongoid/association/constrainable.rb +1 -1
  7. data/lib/mongoid/association/depending.rb +4 -4
  8. data/lib/mongoid/association/embedded/batchable.rb +1 -1
  9. data/lib/mongoid/association/embedded/embedded_in.rb +1 -1
  10. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +10 -3
  11. data/lib/mongoid/association/nested/many.rb +1 -1
  12. data/lib/mongoid/association/nested/one.rb +4 -2
  13. data/lib/mongoid/association/proxy.rb +6 -1
  14. data/lib/mongoid/association/referenced/auto_save.rb +2 -2
  15. data/lib/mongoid/association/referenced/has_many/enumerable.rb +493 -495
  16. data/lib/mongoid/association/referenced/has_many/proxy.rb +2 -2
  17. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +2 -2
  18. data/lib/mongoid/attributes/projector.rb +120 -0
  19. data/lib/mongoid/attributes.rb +32 -14
  20. data/lib/mongoid/cacheable.rb +2 -2
  21. data/lib/mongoid/clients/factory.rb +22 -8
  22. data/lib/mongoid/clients.rb +1 -1
  23. data/lib/mongoid/config.rb +19 -2
  24. data/lib/mongoid/contextual/aggregable/mongo.rb +10 -8
  25. data/lib/mongoid/copyable.rb +1 -1
  26. data/lib/mongoid/criteria/findable.rb +1 -1
  27. data/lib/mongoid/criteria/queryable/expandable.rb +0 -24
  28. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
  29. data/lib/mongoid/criteria/queryable/extensions.rb +0 -4
  30. data/lib/mongoid/criteria/queryable/mergeable.rb +46 -20
  31. data/lib/mongoid/criteria/queryable/selectable.rb +8 -8
  32. data/lib/mongoid/criteria/queryable/selector.rb +0 -4
  33. data/lib/mongoid/criteria.rb +4 -5
  34. data/lib/mongoid/document.rb +4 -17
  35. data/lib/mongoid/errors/delete_restriction.rb +8 -9
  36. data/lib/mongoid/evolvable.rb +1 -1
  37. data/lib/mongoid/extensions/boolean.rb +1 -2
  38. data/lib/mongoid/extensions/false_class.rb +1 -1
  39. data/lib/mongoid/extensions/hash.rb +2 -2
  40. data/lib/mongoid/extensions/true_class.rb +1 -1
  41. data/lib/mongoid/fields.rb +43 -5
  42. data/lib/mongoid/inspectable.rb +1 -1
  43. data/lib/mongoid/interceptable.rb +3 -1
  44. data/lib/mongoid/matcher/bits.rb +41 -0
  45. data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
  46. data/lib/mongoid/matcher/bits_all_set.rb +20 -0
  47. data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
  48. data/lib/mongoid/matcher/bits_any_set.rb +20 -0
  49. data/lib/mongoid/matcher/elem_match.rb +2 -1
  50. data/lib/mongoid/matcher/expression.rb +9 -14
  51. data/lib/mongoid/matcher/field_expression.rb +4 -5
  52. data/lib/mongoid/matcher/field_operator.rb +13 -11
  53. data/lib/mongoid/matcher/mod.rb +17 -0
  54. data/lib/mongoid/matcher/type.rb +99 -0
  55. data/lib/mongoid/matcher.rb +26 -43
  56. data/lib/mongoid/persistable/deletable.rb +1 -2
  57. data/lib/mongoid/persistable/destroyable.rb +8 -2
  58. data/lib/mongoid/persistable/updatable.rb +27 -2
  59. data/lib/mongoid/query_cache.rb +35 -29
  60. data/lib/mongoid/reloadable.rb +5 -0
  61. data/lib/mongoid/selectable.rb +5 -7
  62. data/lib/mongoid/shardable.rb +21 -5
  63. data/lib/mongoid/touchable.rb +23 -4
  64. data/lib/mongoid/version.rb +1 -1
  65. data/lib/rails/generators/mongoid/config/config_generator.rb +8 -1
  66. data/spec/integration/app_spec.rb +171 -84
  67. data/spec/integration/associations/embeds_many_spec.rb +44 -0
  68. data/spec/integration/associations/has_one_spec.rb +48 -0
  69. data/spec/integration/callbacks_models.rb +49 -0
  70. data/spec/integration/callbacks_spec.rb +216 -0
  71. data/spec/integration/criteria/date_field_spec.rb +1 -1
  72. data/spec/integration/document_spec.rb +30 -0
  73. data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
  74. data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
  75. data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
  76. data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
  77. data/spec/integration/matcher_operator_data/comment.yml +22 -0
  78. data/spec/integration/matcher_operator_data/elem_match.yml +46 -0
  79. data/spec/integration/matcher_operator_data/gt_types.yml +63 -0
  80. data/spec/integration/matcher_operator_data/gte_types.yml +15 -0
  81. data/spec/integration/matcher_operator_data/implicit_traversal.yml +96 -0
  82. data/spec/integration/matcher_operator_data/in.yml +16 -0
  83. data/spec/integration/matcher_operator_data/lt_types.yml +15 -0
  84. data/spec/integration/matcher_operator_data/lte_types.yml +15 -0
  85. data/spec/integration/matcher_operator_data/mod.yml +55 -0
  86. data/spec/integration/matcher_operator_data/ne_types.yml +15 -0
  87. data/spec/integration/matcher_operator_data/type.yml +70 -0
  88. data/spec/integration/matcher_operator_data/type_array.yml +16 -0
  89. data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
  90. data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
  91. data/spec/integration/matcher_operator_data/type_code.yml +26 -0
  92. data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
  93. data/spec/integration/matcher_operator_data/type_date.yml +39 -0
  94. data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
  95. data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
  96. data/spec/integration/matcher_operator_data/type_double.yml +15 -0
  97. data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
  98. data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
  99. data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
  100. data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
  101. data/spec/integration/matcher_operator_data/type_null.yml +23 -0
  102. data/spec/integration/matcher_operator_data/type_object.yml +23 -0
  103. data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
  104. data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
  105. data/spec/integration/matcher_operator_data/type_string.yml +15 -0
  106. data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
  107. data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
  108. data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
  109. data/spec/lite_spec_helper.rb +5 -4
  110. data/spec/mongoid/association/depending_spec.rb +391 -352
  111. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +50 -0
  112. data/spec/mongoid/association/nested/one_spec.rb +18 -14
  113. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +25 -8
  114. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +1 -1
  115. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +1 -1
  116. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +1 -1
  117. data/spec/mongoid/association/referenced/has_one_models.rb +8 -0
  118. data/spec/mongoid/atomic/paths_spec.rb +105 -12
  119. data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
  120. data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
  121. data/spec/mongoid/attributes/projector_spec.rb +41 -0
  122. data/spec/mongoid/attributes_spec.rb +333 -0
  123. data/spec/mongoid/clients/factory_spec.rb +48 -0
  124. data/spec/mongoid/config_spec.rb +32 -0
  125. data/spec/mongoid/contextual/atomic_spec.rb +17 -4
  126. data/spec/mongoid/contextual/mongo_spec.rb +2 -2
  127. data/spec/mongoid/criteria/modifiable_spec.rb +1 -1
  128. data/spec/mongoid/criteria/queryable/expandable_spec.rb +0 -73
  129. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +1 -1
  130. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +105 -7
  131. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +265 -24
  132. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +39 -0
  133. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -565
  134. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +590 -0
  135. data/spec/mongoid/criteria_projection_spec.rb +411 -0
  136. data/spec/mongoid/criteria_spec.rb +0 -275
  137. data/spec/mongoid/document_fields_spec.rb +26 -0
  138. data/spec/mongoid/document_spec.rb +13 -13
  139. data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
  140. data/spec/mongoid/extensions/false_class_spec.rb +1 -1
  141. data/spec/mongoid/extensions/string_spec.rb +5 -5
  142. data/spec/mongoid/extensions/true_class_spec.rb +1 -1
  143. data/spec/mongoid/fields/localized_spec.rb +4 -4
  144. data/spec/mongoid/fields_spec.rb +4 -4
  145. data/spec/mongoid/inspectable_spec.rb +12 -4
  146. data/spec/mongoid/matcher/extract_attribute_data/numeric_keys.yml +104 -0
  147. data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +68 -88
  148. data/spec/mongoid/matcher/extract_attribute_spec.rb +3 -13
  149. data/spec/mongoid/persistable/deletable_spec.rb +175 -1
  150. data/spec/mongoid/persistable/destroyable_spec.rb +191 -3
  151. data/spec/mongoid/persistable/savable_spec.rb +3 -5
  152. data/spec/mongoid/persistable/settable_spec.rb +30 -0
  153. data/spec/mongoid/persistable/upsertable_spec.rb +1 -1
  154. data/spec/mongoid/query_cache_middleware_spec.rb +8 -0
  155. data/spec/mongoid/reloadable_spec.rb +18 -1
  156. data/spec/mongoid/shardable_spec.rb +44 -0
  157. data/spec/mongoid/touchable_spec.rb +104 -16
  158. data/spec/mongoid/touchable_spec_models.rb +52 -0
  159. data/spec/mongoid/validatable_spec.rb +1 -1
  160. data/spec/shared/bin/get-mongodb-download-url +17 -0
  161. data/spec/shared/lib/mrss/cluster_config.rb +221 -0
  162. data/spec/shared/lib/mrss/constraints.rb +51 -0
  163. data/spec/shared/lib/mrss/docker_runner.rb +265 -0
  164. data/spec/shared/lib/mrss/lite_constraints.rb +16 -0
  165. data/spec/shared/lib/mrss/server_version_registry.rb +115 -0
  166. data/spec/shared/lib/mrss/spec_organizer.rb +14 -1
  167. data/spec/shared/lib/mrss/utils.rb +15 -0
  168. data/spec/shared/share/Dockerfile.erb +231 -0
  169. data/spec/shared/shlib/distro.sh +73 -0
  170. data/spec/shared/shlib/server.sh +290 -0
  171. data/spec/shared/shlib/set_env.sh +128 -0
  172. data/spec/spec_helper.rb +6 -2
  173. data/spec/support/client_registry.rb +9 -0
  174. data/spec/support/models/bolt.rb +8 -0
  175. data/spec/support/models/customer.rb +11 -0
  176. data/spec/support/models/customer_address.rb +12 -0
  177. data/spec/support/models/dictionary.rb +6 -0
  178. data/spec/support/models/hole.rb +13 -0
  179. data/spec/support/models/mop.rb +9 -0
  180. data/spec/support/models/nut.rb +8 -0
  181. data/spec/support/models/person.rb +6 -0
  182. data/spec/support/models/sealer.rb +8 -0
  183. data/spec/support/models/shirt.rb +12 -0
  184. data/spec/support/models/spacer.rb +8 -0
  185. data/spec/support/models/threadlocker.rb +8 -0
  186. data/spec/support/models/washer.rb +8 -0
  187. data/spec/support/spec_config.rb +8 -0
  188. data.tar.gz.sig +0 -0
  189. metadata +146 -14
  190. metadata.gz.sig +5 -2
  191. data/spec/support/cluster_config.rb +0 -158
@@ -19,103 +19,125 @@ describe 'Mongoid application tests' do
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
28
-
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
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
29
+
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
- Mrss::ChildProcessHelper.check_call(%w(gem uni rails -a))
95
- Mrss::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
- Mrss::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
- Mrss::ChildProcessHelper.check_call(%w(bundle install), env: clean_env)
104
-
105
- Mrss::ChildProcessHelper.check_call(%w(rails g model post), env: clean_env)
106
- Mrss::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
 
@@ -150,7 +172,7 @@ describe 'Mongoid application tests' do
150
172
  end
151
173
  index.should be nil
152
174
 
153
- Mrss::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,12 +187,13 @@ 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
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)
195
+ adjust_app_gemfile
196
+ adjust_rails_defaults
174
197
  Mrss::ChildProcessHelper.check_call(%w(bundle install), env: clean_env)
175
198
  puts `git diff`
176
199
 
@@ -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,13 +261,41 @@ 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
216
300
  lock_lines = IO.readlines('Gemfile.lock')
217
301
  # Get rid of the bundled with line so that whatever bundler is installed
@@ -237,7 +321,7 @@ describe 'Mongoid application tests' do
237
321
  @clean_env ||= Hash[ENV.keys.grep(/BUNDLE|RUBYOPT/).map { |k| [k, nil ] }]
238
322
  end
239
323
 
240
- def wait_for_port(port, timeout)
324
+ def wait_for_port(port, timeout, process)
241
325
  deadline = Time.now + timeout
242
326
  loop do
243
327
  begin
@@ -245,6 +329,9 @@ describe 'Mongoid application tests' do
245
329
  return
246
330
  end
247
331
  rescue IOError, SystemCallError
332
+ unless process.alive?
333
+ raise "Process #{process} died while waiting for port #{port}"
334
+ end
248
335
  if Time.now > deadline
249
336
  raise
250
337
  end
@@ -21,4 +21,48 @@ describe 'embeds_many associations' do
21
21
  end
22
22
  end
23
23
  end
24
+
25
+ context 'clearing association when parent is not saved' do
26
+ let!(:parent) { Canvas.create!(shapes: [Shape.new]) }
27
+
28
+ let(:unsaved_parent) { Canvas.new(id: parent.id, shapes: [Shape.new]) }
29
+
30
+ context "using #clear" do
31
+ it 'deletes the target from the database' do
32
+ unsaved_parent.shapes.clear
33
+
34
+ unsaved_parent.shapes.should be_empty
35
+
36
+ unsaved_parent.new_record?.should be true
37
+ parent.reload
38
+ parent.shapes.should be_empty
39
+ end
40
+ end
41
+
42
+ shared_examples 'does not delete the target from the database' do
43
+ it 'does not delete the target from the database' do
44
+ unsaved_parent.shapes.should be_empty
45
+
46
+ unsaved_parent.new_record?.should be true
47
+ parent.reload
48
+ parent.shapes.length.should == 1
49
+ end
50
+ end
51
+
52
+ context "using #delete_all" do
53
+ before do
54
+ unsaved_parent.shapes.delete_all
55
+ end
56
+
57
+ include_examples 'does not delete the target from the database'
58
+ end
59
+
60
+ context "using #destroy_all" do
61
+ before do
62
+ unsaved_parent.shapes.destroy_all
63
+ end
64
+
65
+ include_examples 'does not delete the target from the database'
66
+ end
67
+ end
24
68
  end
@@ -67,6 +67,54 @@ describe 'has_one associations' do
67
67
  end
68
68
  end
69
69
 
70
+ context 'when calling methods on target' do
71
+ let(:parent) do
72
+ HomCollege.create!.tap do |college|
73
+ HomAccreditation.create!(college: college)
74
+ end
75
+ end
76
+
77
+ shared_examples 'delegates to the field' do |reloaded: false|
78
+ context 'non-conflicting field name' do
79
+ it 'delegates to the field' do
80
+ parent.accreditation.price.should == 42
81
+ end
82
+
83
+ context 'using send' do
84
+ it 'delegates to the field' do
85
+ parent.accreditation.send(:price).should == 42
86
+ end
87
+ end
88
+ end
89
+
90
+ context 'field name that conflicts with Kernel' do
91
+ it 'delegates to the field' do
92
+ parent.accreditation.format.should == 'fmt'
93
+ end
94
+
95
+ context 'using send' do
96
+ it 'delegates to the field' do
97
+ if reloaded
98
+ pending 'MONGOID-4018'
99
+ end
100
+
101
+ parent.accreditation.send(:format).should == 'fmt'
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ include_examples 'delegates to the field'
108
+
109
+ context 'after reloading parent' do
110
+ before do
111
+ parent.reload
112
+ end
113
+
114
+ include_examples 'delegates to the field', reloaded: true
115
+ end
116
+ end
117
+
70
118
  context 'when child does not have parent association' do
71
119
  context 'Child.new' do
72
120
  it 'creates a child instance' do
@@ -0,0 +1,49 @@
1
+ class Galaxy
2
+ include Mongoid::Document
3
+
4
+ field :age, type: Integer
5
+
6
+ before_validation :set_age
7
+
8
+ embeds_many :stars
9
+
10
+ private
11
+
12
+ def set_age
13
+ self.age ||= 100_000
14
+ end
15
+ end
16
+
17
+ class Star
18
+ include Mongoid::Document
19
+
20
+ embedded_in :galaxy
21
+
22
+ field :age, type: Integer
23
+
24
+ before_validation :set_age
25
+
26
+ embeds_many :planets
27
+
28
+ private
29
+
30
+ def set_age
31
+ self.age ||= 42_000
32
+ end
33
+ end
34
+
35
+ class Planet
36
+ include Mongoid::Document
37
+
38
+ embedded_in :star
39
+
40
+ field :age, type: Integer
41
+
42
+ before_validation :set_age
43
+
44
+ private
45
+
46
+ def set_age
47
+ self.age ||= 2_000
48
+ end
49
+ end