mongoid 7.0.5 → 8.1.5

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 (1108) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +33 -33
  4. data/LICENSE +1 -0
  5. data/README.md +34 -20
  6. data/Rakefile +88 -5
  7. data/lib/config/locales/en.yml +220 -105
  8. data/lib/mongoid/association/accessors.rb +176 -84
  9. data/lib/mongoid/association/bindable.rb +57 -28
  10. data/lib/mongoid/association/builders.rb +9 -15
  11. data/lib/mongoid/association/constrainable.rb +5 -7
  12. data/lib/mongoid/association/depending.rb +9 -18
  13. data/lib/mongoid/association/eager_loadable.rb +31 -10
  14. data/lib/mongoid/association/embedded/batchable.rb +68 -54
  15. data/lib/mongoid/association/embedded/cyclic.rb +10 -17
  16. data/lib/mongoid/association/embedded/embedded_in/binding.rb +27 -9
  17. data/lib/mongoid/association/embedded/embedded_in/buildable.rb +9 -6
  18. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +16 -25
  19. data/lib/mongoid/association/embedded/embedded_in.rb +9 -28
  20. data/lib/mongoid/association/embedded/embeds_many/binding.rb +5 -8
  21. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +10 -6
  22. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +172 -136
  23. data/lib/mongoid/association/embedded/embeds_many.rb +10 -37
  24. data/lib/mongoid/association/embedded/embeds_one/binding.rb +4 -8
  25. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +27 -10
  26. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +64 -30
  27. data/lib/mongoid/association/embedded/embeds_one.rb +11 -34
  28. data/lib/mongoid/association/embedded.rb +2 -0
  29. data/lib/mongoid/association/macros.rb +71 -41
  30. data/lib/mongoid/association/many.rb +25 -35
  31. data/lib/mongoid/association/marshalable.rb +3 -6
  32. data/lib/mongoid/association/nested/many.rb +22 -30
  33. data/lib/mongoid/association/nested/nested_buildable.rb +9 -15
  34. data/lib/mongoid/association/nested/one.rb +57 -30
  35. data/lib/mongoid/association/nested.rb +3 -3
  36. data/lib/mongoid/association/one.rb +5 -12
  37. data/lib/mongoid/association/options.rb +16 -46
  38. data/lib/mongoid/association/proxy.rb +52 -40
  39. data/lib/mongoid/association/referenced/auto_save.rb +9 -14
  40. data/lib/mongoid/association/referenced/belongs_to/binding.rb +5 -9
  41. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +11 -9
  42. data/lib/mongoid/association/referenced/belongs_to/eager.rb +40 -3
  43. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +19 -31
  44. data/lib/mongoid/association/referenced/belongs_to.rb +16 -38
  45. data/lib/mongoid/association/referenced/counter_cache.rb +14 -25
  46. data/lib/mongoid/association/referenced/eager.rb +41 -40
  47. data/lib/mongoid/association/referenced/has_and_belongs_to_many/binding.rb +12 -11
  48. data/lib/mongoid/association/referenced/has_and_belongs_to_many/buildable.rb +5 -5
  49. data/lib/mongoid/association/referenced/has_and_belongs_to_many/eager.rb +2 -1
  50. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +105 -68
  51. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +29 -46
  52. data/lib/mongoid/association/referenced/has_many/binding.rb +3 -6
  53. data/lib/mongoid/association/referenced/has_many/buildable.rb +5 -5
  54. data/lib/mongoid/association/referenced/has_many/eager.rb +2 -1
  55. data/lib/mongoid/association/referenced/has_many/enumerable.rb +440 -456
  56. data/lib/mongoid/association/referenced/has_many/proxy.rb +113 -127
  57. data/lib/mongoid/association/referenced/has_many.rb +21 -45
  58. data/lib/mongoid/association/referenced/has_one/binding.rb +4 -9
  59. data/lib/mongoid/association/referenced/has_one/buildable.rb +20 -6
  60. data/lib/mongoid/association/referenced/has_one/eager.rb +2 -1
  61. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +16 -29
  62. data/lib/mongoid/association/referenced/has_one/proxy.rb +25 -30
  63. data/lib/mongoid/association/referenced/has_one.rb +16 -36
  64. data/lib/mongoid/association/referenced/syncable.rb +11 -26
  65. data/lib/mongoid/association/referenced.rb +2 -0
  66. data/lib/mongoid/association/reflections.rb +7 -6
  67. data/lib/mongoid/association/relatable.rb +62 -84
  68. data/lib/mongoid/association.rb +13 -27
  69. data/lib/mongoid/atomic/modifiers.rb +29 -53
  70. data/lib/mongoid/atomic/paths/embedded/many.rb +23 -7
  71. data/lib/mongoid/atomic/paths/embedded/one.rb +4 -7
  72. data/lib/mongoid/atomic/paths/embedded.rb +2 -3
  73. data/lib/mongoid/atomic/paths/root.rb +4 -7
  74. data/lib/mongoid/atomic/paths.rb +2 -1
  75. data/lib/mongoid/atomic.rb +51 -47
  76. data/lib/mongoid/attributes/dynamic.rb +22 -36
  77. data/lib/mongoid/attributes/nested.rb +12 -15
  78. data/lib/mongoid/attributes/processing.rb +46 -30
  79. data/lib/mongoid/attributes/projector.rb +119 -0
  80. data/lib/mongoid/attributes/readonly.rb +6 -9
  81. data/lib/mongoid/attributes.rb +103 -100
  82. data/lib/mongoid/cacheable.rb +7 -10
  83. data/lib/mongoid/changeable.rb +152 -73
  84. data/lib/mongoid/clients/factory.rb +42 -17
  85. data/lib/mongoid/clients/options.rb +15 -14
  86. data/lib/mongoid/clients/sessions.rb +10 -10
  87. data/lib/mongoid/clients/storage_options.rb +9 -17
  88. data/lib/mongoid/clients/validators/storage.rb +5 -24
  89. data/lib/mongoid/clients/validators.rb +2 -1
  90. data/lib/mongoid/clients.rb +3 -10
  91. data/lib/mongoid/collection_configurable.rb +58 -0
  92. data/lib/mongoid/composable.rb +7 -9
  93. data/lib/mongoid/config/defaults.rb +60 -0
  94. data/lib/mongoid/config/environment.rb +51 -13
  95. data/lib/mongoid/config/options.rb +23 -23
  96. data/lib/mongoid/config/validators/async_query_executor.rb +24 -0
  97. data/lib/mongoid/config/validators/client.rb +8 -23
  98. data/lib/mongoid/config/validators/option.rb +2 -3
  99. data/lib/mongoid/config/validators.rb +3 -1
  100. data/lib/mongoid/config.rb +265 -48
  101. data/lib/mongoid/contextual/aggregable/memory.rb +40 -27
  102. data/lib/mongoid/contextual/aggregable/mongo.rb +32 -33
  103. data/lib/mongoid/contextual/aggregable/none.rb +65 -0
  104. data/lib/mongoid/contextual/aggregable.rb +17 -0
  105. data/lib/mongoid/contextual/atomic.rb +29 -31
  106. data/lib/mongoid/contextual/command.rb +2 -5
  107. data/lib/mongoid/contextual/geo_near.rb +13 -44
  108. data/lib/mongoid/contextual/map_reduce.rb +7 -35
  109. data/lib/mongoid/contextual/memory.rb +387 -81
  110. data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
  111. data/lib/mongoid/contextual/mongo.rb +664 -283
  112. data/lib/mongoid/contextual/none.rb +264 -31
  113. data/lib/mongoid/contextual/queryable.rb +3 -4
  114. data/lib/mongoid/contextual.rb +21 -11
  115. data/lib/mongoid/copyable.rb +42 -17
  116. data/lib/mongoid/criteria/findable.rb +20 -20
  117. data/lib/mongoid/criteria/includable.rb +32 -34
  118. data/lib/mongoid/criteria/inspectable.rb +2 -3
  119. data/lib/mongoid/criteria/marshalable.rb +12 -7
  120. data/lib/mongoid/criteria/modifiable.rb +4 -20
  121. data/lib/mongoid/criteria/options.rb +2 -3
  122. data/lib/mongoid/criteria/permission.rb +3 -2
  123. data/lib/mongoid/criteria/queryable/aggregable.rb +4 -15
  124. data/lib/mongoid/criteria/queryable/expandable.rb +68 -0
  125. data/lib/mongoid/criteria/queryable/extensions/array.rb +7 -41
  126. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +28 -8
  127. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +5 -6
  128. data/lib/mongoid/criteria/queryable/extensions/date.rb +9 -9
  129. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +11 -12
  130. data/lib/mongoid/criteria/queryable/extensions/hash.rb +4 -41
  131. data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +3 -14
  132. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +4 -21
  133. data/lib/mongoid/criteria/queryable/extensions/object.rb +6 -30
  134. data/lib/mongoid/criteria/queryable/extensions/range.rb +49 -17
  135. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +12 -19
  136. data/lib/mongoid/criteria/queryable/extensions/set.rb +4 -5
  137. data/lib/mongoid/criteria/queryable/extensions/string.rb +7 -32
  138. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +7 -22
  139. data/lib/mongoid/criteria/queryable/extensions/time.rb +10 -10
  140. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +19 -7
  141. data/lib/mongoid/criteria/queryable/extensions.rb +1 -4
  142. data/lib/mongoid/criteria/queryable/key.rb +40 -25
  143. data/lib/mongoid/criteria/queryable/macroable.rb +3 -4
  144. data/lib/mongoid/criteria/queryable/mergeable.rb +205 -44
  145. data/lib/mongoid/criteria/queryable/optional.rb +16 -65
  146. data/lib/mongoid/criteria/queryable/options.rb +4 -21
  147. data/lib/mongoid/criteria/queryable/pipeline.rb +5 -15
  148. data/lib/mongoid/criteria/queryable/selectable.rb +453 -177
  149. data/lib/mongoid/criteria/queryable/selector.rb +127 -30
  150. data/lib/mongoid/criteria/queryable/smash.rb +42 -18
  151. data/lib/mongoid/criteria/queryable/storable.rb +237 -0
  152. data/lib/mongoid/criteria/queryable.rb +18 -15
  153. data/lib/mongoid/criteria/scopable.rb +29 -21
  154. data/lib/mongoid/criteria/translator.rb +45 -0
  155. data/lib/mongoid/criteria.rb +106 -111
  156. data/lib/mongoid/deprecable.rb +37 -0
  157. data/lib/mongoid/deprecation.rb +25 -0
  158. data/lib/mongoid/document.rb +151 -99
  159. data/lib/mongoid/equality.rb +35 -18
  160. data/lib/mongoid/errors/ambiguous_relationship.rb +4 -5
  161. data/lib/mongoid/errors/callback.rb +2 -3
  162. data/lib/mongoid/errors/create_collection_failure.rb +33 -0
  163. data/lib/mongoid/errors/criteria_argument_required.rb +18 -0
  164. data/lib/mongoid/errors/delete_restriction.rb +10 -13
  165. data/lib/mongoid/errors/document_not_destroyed.rb +4 -7
  166. data/lib/mongoid/errors/document_not_found.rb +35 -21
  167. data/lib/mongoid/errors/drop_collection_failure.rb +27 -0
  168. data/lib/mongoid/errors/empty_config_file.rb +25 -0
  169. data/lib/mongoid/errors/immutable_attribute.rb +26 -0
  170. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +2 -3
  171. data/lib/mongoid/errors/invalid_async_query_executor.rb +25 -0
  172. data/lib/mongoid/errors/invalid_collection.rb +2 -1
  173. data/lib/mongoid/errors/invalid_config_file.rb +25 -0
  174. data/lib/mongoid/errors/invalid_config_option.rb +3 -4
  175. data/lib/mongoid/errors/invalid_dependent_strategy.rb +3 -4
  176. data/lib/mongoid/errors/invalid_discriminator_key_target.rb +24 -0
  177. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  178. data/lib/mongoid/errors/invalid_elem_match_operator.rb +32 -0
  179. data/lib/mongoid/errors/invalid_estimated_count_criteria.rb +25 -0
  180. data/lib/mongoid/errors/invalid_expression_operator.rb +27 -0
  181. data/lib/mongoid/errors/invalid_field.rb +8 -7
  182. data/lib/mongoid/errors/invalid_field_operator.rb +32 -0
  183. data/lib/mongoid/errors/invalid_field_option.rb +2 -3
  184. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  185. data/lib/mongoid/errors/invalid_find.rb +2 -3
  186. data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +22 -0
  187. data/lib/mongoid/errors/invalid_includes.rb +2 -3
  188. data/lib/mongoid/errors/invalid_index.rb +2 -3
  189. data/lib/mongoid/errors/invalid_options.rb +4 -5
  190. data/lib/mongoid/errors/invalid_path.rb +2 -3
  191. data/lib/mongoid/errors/invalid_persistence_option.rb +2 -5
  192. data/lib/mongoid/errors/invalid_query.rb +40 -0
  193. data/lib/mongoid/errors/invalid_relation.rb +5 -10
  194. data/lib/mongoid/errors/invalid_relation_option.rb +4 -5
  195. data/lib/mongoid/errors/invalid_scope.rb +2 -3
  196. data/lib/mongoid/errors/invalid_session_use.rb +3 -6
  197. data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +6 -5
  198. data/lib/mongoid/errors/invalid_storage_options.rb +3 -4
  199. data/lib/mongoid/errors/invalid_storage_parent.rb +4 -3
  200. data/lib/mongoid/errors/invalid_time.rb +2 -3
  201. data/lib/mongoid/errors/inverse_not_found.rb +3 -4
  202. data/lib/mongoid/errors/mixed_client_configuration.rb +2 -3
  203. data/lib/mongoid/errors/mixed_relations.rb +2 -3
  204. data/lib/mongoid/errors/mongoid_error.rb +6 -13
  205. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +3 -4
  206. data/lib/mongoid/errors/no_client_config.rb +4 -5
  207. data/lib/mongoid/errors/no_client_database.rb +3 -4
  208. data/lib/mongoid/errors/no_client_hosts.rb +3 -4
  209. data/lib/mongoid/errors/no_clients_config.rb +2 -3
  210. data/lib/mongoid/errors/no_default_client.rb +3 -4
  211. data/lib/mongoid/errors/no_environment.rb +2 -3
  212. data/lib/mongoid/errors/no_map_reduce_output.rb +2 -3
  213. data/lib/mongoid/errors/no_metadata.rb +2 -3
  214. data/lib/mongoid/errors/no_parent.rb +2 -3
  215. data/lib/mongoid/errors/readonly_attribute.rb +3 -4
  216. data/lib/mongoid/errors/readonly_document.rb +3 -6
  217. data/lib/mongoid/errors/scope_overwrite.rb +2 -1
  218. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +3 -1
  219. data/lib/mongoid/errors/unknown_attribute.rb +3 -4
  220. data/lib/mongoid/errors/unknown_model.rb +2 -3
  221. data/lib/mongoid/errors/unsaved_document.rb +3 -2
  222. data/lib/mongoid/errors/unsupported_javascript.rb +2 -3
  223. data/lib/mongoid/errors/validations.rb +2 -1
  224. data/lib/mongoid/errors.rb +18 -4
  225. data/lib/mongoid/evolvable.rb +4 -5
  226. data/lib/mongoid/extensions/array.rb +37 -44
  227. data/lib/mongoid/extensions/big_decimal.rb +35 -21
  228. data/lib/mongoid/extensions/binary.rb +42 -0
  229. data/lib/mongoid/extensions/boolean.rb +10 -6
  230. data/lib/mongoid/extensions/date.rb +32 -25
  231. data/lib/mongoid/extensions/date_time.rb +5 -13
  232. data/lib/mongoid/extensions/decimal128.rb +2 -5
  233. data/lib/mongoid/extensions/false_class.rb +5 -8
  234. data/lib/mongoid/extensions/float.rb +12 -14
  235. data/lib/mongoid/extensions/hash.rb +91 -47
  236. data/lib/mongoid/extensions/integer.rb +12 -16
  237. data/lib/mongoid/extensions/module.rb +3 -4
  238. data/lib/mongoid/extensions/nil_class.rb +2 -5
  239. data/lib/mongoid/extensions/object.rb +27 -52
  240. data/lib/mongoid/extensions/object_id.rb +2 -7
  241. data/lib/mongoid/extensions/range.rb +42 -20
  242. data/lib/mongoid/extensions/regexp.rb +14 -8
  243. data/lib/mongoid/extensions/set.rb +13 -11
  244. data/lib/mongoid/extensions/string.rb +30 -61
  245. data/lib/mongoid/extensions/symbol.rb +6 -22
  246. data/lib/mongoid/extensions/time.rb +38 -22
  247. data/lib/mongoid/extensions/time_with_zone.rb +26 -9
  248. data/lib/mongoid/extensions/true_class.rb +5 -8
  249. data/lib/mongoid/extensions.rb +19 -3
  250. data/lib/mongoid/factory.rb +104 -17
  251. data/lib/mongoid/fields/foreign_key.rb +14 -26
  252. data/lib/mongoid/fields/localized.rb +21 -15
  253. data/lib/mongoid/fields/standard.rb +23 -43
  254. data/lib/mongoid/fields/validators/macro.rb +32 -20
  255. data/lib/mongoid/fields/validators.rb +2 -1
  256. data/lib/mongoid/fields.rb +360 -76
  257. data/lib/mongoid/findable.rb +115 -34
  258. data/lib/mongoid/indexable/specification.rb +5 -18
  259. data/lib/mongoid/indexable/validators/options.rb +8 -9
  260. data/lib/mongoid/indexable.rb +6 -21
  261. data/lib/mongoid/inspectable.rb +4 -11
  262. data/lib/mongoid/interceptable.rb +195 -42
  263. data/lib/mongoid/loggable.rb +13 -16
  264. data/lib/mongoid/matchable.rb +4 -156
  265. data/lib/mongoid/matcher/all.rb +22 -0
  266. data/lib/mongoid/matcher/and.rb +21 -0
  267. data/lib/mongoid/matcher/bits.rb +41 -0
  268. data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
  269. data/lib/mongoid/matcher/bits_all_set.rb +20 -0
  270. data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
  271. data/lib/mongoid/matcher/bits_any_set.rb +20 -0
  272. data/lib/mongoid/matcher/elem_match.rb +36 -0
  273. data/lib/mongoid/matcher/elem_match_expression.rb +20 -0
  274. data/lib/mongoid/matcher/eq.rb +11 -0
  275. data/lib/mongoid/matcher/eq_impl.rb +67 -0
  276. data/lib/mongoid/matcher/eq_impl_with_regexp.rb +26 -0
  277. data/lib/mongoid/matcher/exists.rb +15 -0
  278. data/lib/mongoid/matcher/expression.rb +35 -0
  279. data/lib/mongoid/matcher/expression_operator.rb +19 -0
  280. data/lib/mongoid/matcher/field_expression.rb +62 -0
  281. data/lib/mongoid/matcher/field_operator.rb +54 -0
  282. data/lib/mongoid/matcher/gt.rb +17 -0
  283. data/lib/mongoid/matcher/gte.rb +17 -0
  284. data/lib/mongoid/matcher/in.rb +25 -0
  285. data/lib/mongoid/matcher/lt.rb +17 -0
  286. data/lib/mongoid/matcher/lte.rb +17 -0
  287. data/lib/mongoid/matcher/mod.rb +17 -0
  288. data/lib/mongoid/matcher/ne.rb +16 -0
  289. data/lib/mongoid/matcher/nin.rb +11 -0
  290. data/lib/mongoid/matcher/nor.rb +25 -0
  291. data/lib/mongoid/matcher/not.rb +29 -0
  292. data/lib/mongoid/matcher/or.rb +21 -0
  293. data/lib/mongoid/matcher/regex.rb +41 -0
  294. data/lib/mongoid/matcher/size.rb +26 -0
  295. data/lib/mongoid/matcher/type.rb +99 -0
  296. data/lib/mongoid/matcher.rb +130 -0
  297. data/lib/mongoid/persistable/creatable.rb +23 -30
  298. data/lib/mongoid/persistable/deletable.rb +7 -23
  299. data/lib/mongoid/persistable/destroyable.rb +12 -11
  300. data/lib/mongoid/persistable/incrementable.rb +6 -7
  301. data/lib/mongoid/persistable/logical.rb +4 -6
  302. data/lib/mongoid/persistable/poppable.rb +3 -6
  303. data/lib/mongoid/persistable/pullable.rb +3 -8
  304. data/lib/mongoid/persistable/pushable.rb +14 -10
  305. data/lib/mongoid/persistable/renamable.rb +10 -8
  306. data/lib/mongoid/persistable/savable.rb +16 -9
  307. data/lib/mongoid/persistable/settable.rb +3 -6
  308. data/lib/mongoid/persistable/unsettable.rb +10 -10
  309. data/lib/mongoid/persistable/updatable.rb +99 -30
  310. data/lib/mongoid/persistable/upsertable.rb +23 -9
  311. data/lib/mongoid/persistable.rb +138 -40
  312. data/lib/mongoid/persistence_context.rb +91 -51
  313. data/lib/mongoid/positional.rb +2 -5
  314. data/lib/mongoid/query_cache.rb +18 -238
  315. data/lib/mongoid/railtie.rb +3 -16
  316. data/lib/mongoid/railties/controller_runtime.rb +4 -2
  317. data/lib/mongoid/railties/database.rake +16 -2
  318. data/lib/mongoid/reloadable.rb +19 -22
  319. data/lib/mongoid/scopable.rb +34 -57
  320. data/lib/mongoid/selectable.rb +8 -18
  321. data/lib/mongoid/serializable.rb +33 -34
  322. data/lib/mongoid/shardable.rb +108 -21
  323. data/lib/mongoid/stateful.rb +60 -20
  324. data/lib/mongoid/stringified_symbol.rb +52 -0
  325. data/lib/mongoid/tasks/database.rake +24 -5
  326. data/lib/mongoid/tasks/database.rb +105 -7
  327. data/lib/mongoid/threaded/lifecycle.rb +7 -26
  328. data/lib/mongoid/threaded.rb +44 -67
  329. data/lib/mongoid/timestamps/created/short.rb +2 -1
  330. data/lib/mongoid/timestamps/created.rb +4 -3
  331. data/lib/mongoid/timestamps/short.rb +2 -1
  332. data/lib/mongoid/timestamps/timeless.rb +6 -9
  333. data/lib/mongoid/timestamps/updated/short.rb +2 -1
  334. data/lib/mongoid/timestamps/updated.rb +5 -6
  335. data/lib/mongoid/timestamps.rb +3 -2
  336. data/lib/mongoid/touchable.rb +54 -25
  337. data/lib/mongoid/traversable.rb +185 -61
  338. data/lib/mongoid/utils.rb +22 -0
  339. data/lib/mongoid/validatable/associated.rb +99 -22
  340. data/lib/mongoid/validatable/format.rb +2 -1
  341. data/lib/mongoid/validatable/length.rb +2 -1
  342. data/lib/mongoid/validatable/localizable.rb +3 -4
  343. data/lib/mongoid/validatable/macros.rb +7 -14
  344. data/lib/mongoid/validatable/presence.rb +10 -15
  345. data/lib/mongoid/validatable/queryable.rb +2 -3
  346. data/lib/mongoid/validatable/uniqueness.rb +30 -42
  347. data/lib/mongoid/validatable.rb +24 -32
  348. data/lib/mongoid/version.rb +3 -2
  349. data/lib/mongoid/warnings.rb +44 -0
  350. data/lib/mongoid.rb +50 -17
  351. data/lib/rails/generators/mongoid/config/config_generator.rb +10 -2
  352. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +53 -32
  353. data/lib/rails/generators/mongoid/model/model_generator.rb +3 -2
  354. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
  355. data/lib/rails/generators/mongoid_generator.rb +2 -1
  356. data/lib/rails/mongoid.rb +4 -5
  357. data/spec/README.md +19 -4
  358. data/spec/config/mongoid.yml +17 -0
  359. data/spec/config/mongoid_with_schema_map_uuid.yml +27 -0
  360. data/spec/integration/app_spec.rb +345 -0
  361. data/spec/integration/associations/belongs_to_spec.rb +20 -0
  362. data/spec/integration/associations/embedded_dirty_spec.rb +57 -0
  363. data/spec/integration/associations/embedded_spec.rb +283 -0
  364. data/spec/integration/associations/embeds_many_spec.rb +219 -0
  365. data/spec/integration/associations/embeds_one_spec.rb +41 -0
  366. data/spec/integration/associations/foreign_key_spec.rb +107 -0
  367. data/spec/integration/associations/foreign_key_spec_models.rb +64 -0
  368. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +61 -0
  369. data/spec/integration/associations/has_many_spec.rb +128 -0
  370. data/spec/integration/associations/has_one_spec.rb +272 -0
  371. data/spec/integration/associations/nested_attributes_assignment_spec.rb +115 -0
  372. data/spec/integration/associations/reverse_population_spec.rb +34 -0
  373. data/spec/integration/associations/reverse_population_spec_models.rb +36 -0
  374. data/spec/integration/associations/scope_option_spec.rb +101 -0
  375. data/spec/integration/atomic/modifiers_spec.rb +116 -0
  376. data/spec/integration/bson_regexp_raw_spec.rb +19 -0
  377. data/spec/integration/callbacks_models.rb +192 -0
  378. data/spec/integration/callbacks_spec.rb +605 -0
  379. data/spec/integration/contextual/empty_spec.rb +141 -0
  380. data/spec/integration/criteria/alias_query_spec.rb +161 -0
  381. data/spec/integration/criteria/date_field_spec.rb +40 -0
  382. data/spec/integration/criteria/default_scope_spec.rb +72 -0
  383. data/spec/integration/criteria/logical_spec.rb +124 -0
  384. data/spec/integration/criteria/range_spec.rb +359 -0
  385. data/spec/integration/criteria/time_with_zone_spec.rb +142 -0
  386. data/spec/integration/discriminator_key_spec.rb +391 -0
  387. data/spec/integration/discriminator_value_spec.rb +206 -0
  388. data/spec/integration/document_spec.rb +51 -0
  389. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  390. data/spec/integration/i18n_fallbacks_spec.rb +74 -0
  391. data/spec/integration/matcher_examples_spec.rb +765 -0
  392. data/spec/integration/matcher_operator_data/all.yml +140 -0
  393. data/spec/integration/matcher_operator_data/and.yml +93 -0
  394. data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
  395. data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
  396. data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
  397. data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
  398. data/spec/integration/matcher_operator_data/comment.yml +22 -0
  399. data/spec/integration/matcher_operator_data/elem_match.yml +409 -0
  400. data/spec/integration/matcher_operator_data/elem_match_expr.yml +213 -0
  401. data/spec/integration/matcher_operator_data/eq.yml +191 -0
  402. data/spec/integration/matcher_operator_data/exists.yml +213 -0
  403. data/spec/integration/matcher_operator_data/generic_op.yml +17 -0
  404. data/spec/integration/matcher_operator_data/gt.yml +132 -0
  405. data/spec/integration/matcher_operator_data/gt_types.yml +63 -0
  406. data/spec/integration/matcher_operator_data/gte.yml +132 -0
  407. data/spec/integration/matcher_operator_data/gte_types.yml +15 -0
  408. data/spec/integration/matcher_operator_data/implicit.yml +331 -0
  409. data/spec/integration/matcher_operator_data/implicit_traversal.yml +112 -0
  410. data/spec/integration/matcher_operator_data/in.yml +210 -0
  411. data/spec/integration/matcher_operator_data/invalid_op.yml +59 -0
  412. data/spec/integration/matcher_operator_data/invalid_syntax.yml +39 -0
  413. data/spec/integration/matcher_operator_data/lt.yml +132 -0
  414. data/spec/integration/matcher_operator_data/lt_types.yml +15 -0
  415. data/spec/integration/matcher_operator_data/lte.yml +132 -0
  416. data/spec/integration/matcher_operator_data/lte_types.yml +15 -0
  417. data/spec/integration/matcher_operator_data/mod.yml +55 -0
  418. data/spec/integration/matcher_operator_data/multiple.yml +29 -0
  419. data/spec/integration/matcher_operator_data/ne.yml +150 -0
  420. data/spec/integration/matcher_operator_data/ne_types.yml +15 -0
  421. data/spec/integration/matcher_operator_data/nin.yml +114 -0
  422. data/spec/integration/matcher_operator_data/nor.yml +126 -0
  423. data/spec/integration/matcher_operator_data/not.yml +196 -0
  424. data/spec/integration/matcher_operator_data/or.yml +137 -0
  425. data/spec/integration/matcher_operator_data/regex.yml +174 -0
  426. data/spec/integration/matcher_operator_data/regex_options.yml +72 -0
  427. data/spec/integration/matcher_operator_data/size.yml +174 -0
  428. data/spec/integration/matcher_operator_data/type.yml +70 -0
  429. data/spec/integration/matcher_operator_data/type_array.yml +16 -0
  430. data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
  431. data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
  432. data/spec/integration/matcher_operator_data/type_code.yml +26 -0
  433. data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
  434. data/spec/integration/matcher_operator_data/type_date.yml +39 -0
  435. data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
  436. data/spec/integration/matcher_operator_data/type_decimal.yml +41 -0
  437. data/spec/integration/matcher_operator_data/type_double.yml +15 -0
  438. data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
  439. data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
  440. data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
  441. data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
  442. data/spec/integration/matcher_operator_data/type_null.yml +23 -0
  443. data/spec/integration/matcher_operator_data/type_object.yml +23 -0
  444. data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
  445. data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
  446. data/spec/integration/matcher_operator_data/type_string.yml +15 -0
  447. data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
  448. data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
  449. data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
  450. data/spec/integration/matcher_operator_spec.rb +122 -0
  451. data/spec/integration/matcher_spec.rb +283 -0
  452. data/spec/integration/persistence/range_field_spec.rb +350 -0
  453. data/spec/integration/server_query_spec.rb +141 -0
  454. data/spec/integration/shardable_spec.rb +148 -0
  455. data/spec/integration/stringified_symbol_field_spec.rb +203 -0
  456. data/spec/lite_spec_helper.rb +35 -8
  457. data/spec/mongoid/association/accessors_spec.rb +284 -77
  458. data/spec/mongoid/association/auto_save_spec.rb +74 -33
  459. data/spec/mongoid/association/builders_spec.rb +3 -1
  460. data/spec/mongoid/association/constrainable_spec.rb +2 -0
  461. data/spec/mongoid/association/counter_cache_spec.rb +35 -33
  462. data/spec/mongoid/association/depending_spec.rb +431 -338
  463. data/spec/mongoid/association/eager_spec.rb +8 -5
  464. data/spec/mongoid/association/embedded/cyclic_spec.rb +4 -2
  465. data/spec/mongoid/association/embedded/dirty_spec.rb +4 -2
  466. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +4 -1
  467. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +56 -0
  468. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +152 -13
  469. data/spec/mongoid/association/embedded/embedded_in_spec.rb +3 -1
  470. data/spec/mongoid/association/embedded/embeds_many/binding_spec.rb +2 -0
  471. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +114 -0
  472. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +741 -197
  473. data/spec/mongoid/association/embedded/embeds_many_models.rb +227 -0
  474. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +63 -0
  475. data/spec/mongoid/association/embedded/embeds_many_spec.rb +81 -1
  476. data/spec/mongoid/association/embedded/embeds_one/binding_spec.rb +2 -0
  477. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +27 -0
  478. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +38 -23
  479. data/spec/mongoid/association/embedded/embeds_one_dnl_models.rb +2 -0
  480. data/spec/mongoid/association/embedded/embeds_one_models.rb +22 -0
  481. data/spec/mongoid/association/embedded/embeds_one_query_spec.rb +28 -0
  482. data/spec/mongoid/association/embedded/embeds_one_spec.rb +31 -3
  483. data/spec/mongoid/association/macros_spec.rb +11 -9
  484. data/spec/mongoid/association/nested/many_spec.rb +2 -0
  485. data/spec/mongoid/association/nested/one_spec.rb +18 -12
  486. data/spec/mongoid/association/options_spec.rb +2 -0
  487. data/spec/mongoid/association/polymorphic_spec.rb +2 -0
  488. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +4 -1
  489. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +111 -16
  490. data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +242 -12
  491. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +114 -58
  492. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  493. data/spec/mongoid/association/referenced/belongs_to_query_spec.rb +57 -0
  494. data/spec/mongoid/association/referenced/belongs_to_spec.rb +28 -21
  495. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +3 -1
  496. data/spec/mongoid/association/referenced/has_and_belongs_to_many/buildable_spec.rb +28 -1
  497. data/spec/mongoid/association/referenced/has_and_belongs_to_many/eager_spec.rb +46 -2
  498. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_persistence_spec.rb +25 -5
  499. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +559 -385
  500. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +68 -2
  501. data/spec/mongoid/association/referenced/has_and_belongs_to_many_query_spec.rb +39 -0
  502. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +81 -4
  503. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +3 -1
  504. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +132 -0
  505. data/spec/mongoid/association/referenced/has_many/eager_spec.rb +40 -9
  506. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +415 -129
  507. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +901 -502
  508. data/spec/mongoid/association/referenced/has_many_models.rb +61 -1
  509. data/spec/mongoid/association/referenced/has_many_query_spec.rb +37 -0
  510. data/spec/mongoid/association/referenced/has_many_spec.rb +48 -0
  511. data/spec/mongoid/association/referenced/has_one/binding_spec.rb +2 -0
  512. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +55 -9
  513. data/spec/mongoid/association/referenced/has_one/eager_spec.rb +34 -4
  514. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +135 -27
  515. data/spec/mongoid/association/referenced/has_one_models.rb +65 -0
  516. data/spec/mongoid/association/referenced/has_one_query_spec.rb +37 -0
  517. data/spec/mongoid/association/referenced/has_one_spec.rb +24 -1
  518. data/spec/mongoid/association/reflections_spec.rb +2 -0
  519. data/spec/mongoid/association/syncable_spec.rb +48 -32
  520. data/spec/mongoid/association_spec.rb +2 -0
  521. data/spec/mongoid/atomic/modifiers_spec.rb +49 -0
  522. data/spec/mongoid/atomic/paths/embedded/many_spec.rb +2 -0
  523. data/spec/mongoid/atomic/paths/embedded/one_spec.rb +2 -0
  524. data/spec/mongoid/atomic/paths/root_spec.rb +2 -0
  525. data/spec/mongoid/atomic/paths_spec.rb +93 -12
  526. data/spec/mongoid/atomic_spec.rb +53 -6
  527. data/spec/mongoid/attributes/dynamic_spec.rb +152 -0
  528. data/spec/mongoid/attributes/nested_spec.rb +149 -78
  529. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  530. data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
  531. data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
  532. data/spec/mongoid/attributes/projector_spec.rb +40 -0
  533. data/spec/mongoid/attributes/readonly_spec.rb +24 -22
  534. data/spec/mongoid/attributes_spec.rb +922 -54
  535. data/spec/mongoid/cacheable_spec.rb +6 -4
  536. data/spec/mongoid/changeable_spec.rb +484 -67
  537. data/spec/mongoid/clients/factory_spec.rb +128 -28
  538. data/spec/mongoid/clients/options_spec.rb +49 -30
  539. data/spec/mongoid/clients/sessions_spec.rb +29 -66
  540. data/spec/mongoid/clients/transactions_spec.rb +74 -37
  541. data/spec/mongoid/clients_spec.rb +189 -23
  542. data/spec/mongoid/collection_configurable_spec.rb +158 -0
  543. data/spec/mongoid/composable_spec.rb +2 -0
  544. data/spec/mongoid/config/defaults_spec.rb +160 -0
  545. data/spec/mongoid/config/environment_spec.rb +126 -8
  546. data/spec/mongoid/config/options_spec.rb +22 -3
  547. data/spec/mongoid/config_spec.rb +513 -1
  548. data/spec/mongoid/contextual/aggregable/memory_spec.rb +433 -153
  549. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  550. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  551. data/spec/mongoid/contextual/aggregable/mongo_spec.rb +122 -20
  552. data/spec/mongoid/contextual/aggregable/none_spec.rb +60 -0
  553. data/spec/mongoid/contextual/atomic_spec.rb +242 -81
  554. data/spec/mongoid/contextual/geo_near_spec.rb +30 -19
  555. data/spec/mongoid/contextual/map_reduce_spec.rb +22 -19
  556. data/spec/mongoid/contextual/memory_spec.rb +1828 -303
  557. data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
  558. data/spec/mongoid/contextual/mongo_spec.rb +3514 -1205
  559. data/spec/mongoid/contextual/none_spec.rb +80 -67
  560. data/spec/mongoid/copyable_spec.rb +659 -36
  561. data/spec/mongoid/copyable_spec_models.rb +30 -0
  562. data/spec/mongoid/criteria/findable_spec.rb +161 -228
  563. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  564. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  565. data/spec/mongoid/criteria/inspectable_spec.rb +2 -0
  566. data/spec/mongoid/criteria/marshalable_spec.rb +20 -1
  567. data/spec/mongoid/criteria/modifiable_spec.rb +43 -40
  568. data/spec/mongoid/criteria/options_spec.rb +2 -0
  569. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +3 -1
  570. data/spec/mongoid/criteria/queryable/expandable_spec.rb +61 -0
  571. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +9 -19
  572. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +136 -26
  573. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +3 -1
  574. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +13 -0
  575. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +46 -17
  576. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +2 -0
  577. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +2 -15
  578. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +2 -0
  579. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +2 -0
  580. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -8
  581. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +2 -0
  582. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +239 -178
  583. data/spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb +3 -1
  584. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +9 -7
  585. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +2 -0
  586. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +7 -70
  587. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +2 -59
  588. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +53 -23
  589. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +41 -1
  590. data/spec/mongoid/criteria/queryable/key_spec.rb +2 -0
  591. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +145 -12
  592. data/spec/mongoid/criteria/queryable/optional_spec.rb +18 -485
  593. data/spec/mongoid/criteria/queryable/options_spec.rb +3 -1
  594. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +2 -0
  595. data/spec/mongoid/criteria/queryable/queryable_spec.rb +3 -1
  596. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +2538 -0
  597. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +38 -0
  598. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1100 -2880
  599. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +589 -0
  600. data/spec/mongoid/criteria/queryable/selector_spec.rb +92 -5
  601. data/spec/mongoid/criteria/queryable/smash_spec.rb +2 -0
  602. data/spec/mongoid/criteria/queryable/storable_spec.rb +298 -0
  603. data/spec/mongoid/criteria/scopable_spec.rb +129 -0
  604. data/spec/mongoid/criteria/translator_spec.rb +132 -0
  605. data/spec/mongoid/criteria_projection_spec.rb +406 -0
  606. data/spec/mongoid/criteria_spec.rb +1320 -1723
  607. data/spec/mongoid/document_fields_spec.rb +262 -0
  608. data/spec/mongoid/document_persistence_context_spec.rb +32 -0
  609. data/spec/mongoid/document_query_spec.rb +89 -0
  610. data/spec/mongoid/document_spec.rb +153 -87
  611. data/spec/mongoid/equality_spec.rb +144 -41
  612. data/spec/mongoid/errors/ambiguous_relationship_spec.rb +5 -3
  613. data/spec/mongoid/errors/callback_spec.rb +2 -0
  614. data/spec/mongoid/errors/delete_restriction_spec.rb +4 -2
  615. data/spec/mongoid/errors/document_not_destroyed_spec.rb +2 -0
  616. data/spec/mongoid/errors/document_not_found_spec.rb +78 -0
  617. data/spec/mongoid/errors/invalid_collection_spec.rb +2 -0
  618. data/spec/mongoid/errors/{eager_load_spec.rb → invalid_config_file_spec.rb} +7 -5
  619. data/spec/mongoid/errors/invalid_config_option_spec.rb +2 -0
  620. data/spec/mongoid/errors/invalid_field_option_spec.rb +2 -0
  621. data/spec/mongoid/errors/invalid_field_spec.rb +3 -1
  622. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  623. data/spec/mongoid/errors/invalid_find_spec.rb +2 -0
  624. data/spec/mongoid/errors/invalid_includes_spec.rb +2 -0
  625. data/spec/mongoid/errors/invalid_index_spec.rb +2 -0
  626. data/spec/mongoid/errors/invalid_options_spec.rb +4 -2
  627. data/spec/mongoid/errors/invalid_path_spec.rb +2 -0
  628. data/spec/mongoid/errors/invalid_relation_spec.rb +4 -2
  629. data/spec/mongoid/errors/invalid_scope_spec.rb +3 -1
  630. data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +2 -0
  631. data/spec/mongoid/errors/invalid_storage_options_spec.rb +2 -0
  632. data/spec/mongoid/errors/invalid_time_spec.rb +2 -0
  633. data/spec/mongoid/errors/inverse_not_found_spec.rb +3 -1
  634. data/spec/mongoid/errors/mixed_client_configuration_spec.rb +2 -0
  635. data/spec/mongoid/errors/mixed_relations_spec.rb +2 -0
  636. data/spec/mongoid/errors/mongoid_error_spec.rb +24 -8
  637. data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +5 -3
  638. data/spec/mongoid/errors/no_client_config_spec.rb +4 -2
  639. data/spec/mongoid/errors/no_client_database_spec.rb +5 -3
  640. data/spec/mongoid/errors/no_client_hosts_spec.rb +5 -3
  641. data/spec/mongoid/errors/no_clients_config_spec.rb +2 -0
  642. data/spec/mongoid/errors/no_environment_spec.rb +5 -3
  643. data/spec/mongoid/errors/no_map_reduce_output_spec.rb +2 -0
  644. data/spec/mongoid/errors/no_metadata_spec.rb +4 -2
  645. data/spec/mongoid/errors/no_parent_spec.rb +3 -1
  646. data/spec/mongoid/errors/readonly_attribute_spec.rb +2 -0
  647. data/spec/mongoid/errors/readonly_document_spec.rb +4 -2
  648. data/spec/mongoid/errors/scope_overwrite_spec.rb +2 -0
  649. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +3 -1
  650. data/spec/mongoid/errors/unknown_attribute_spec.rb +4 -2
  651. data/spec/mongoid/errors/unsaved_document_spec.rb +3 -1
  652. data/spec/mongoid/errors/unsupported_javascript_spec.rb +2 -0
  653. data/spec/mongoid/errors/validations_spec.rb +2 -0
  654. data/spec/mongoid/extensions/array_spec.rb +41 -45
  655. data/spec/mongoid/extensions/big_decimal_spec.rb +714 -212
  656. data/spec/mongoid/extensions/binary_spec.rb +46 -9
  657. data/spec/mongoid/extensions/boolean_spec.rb +70 -82
  658. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +339 -0
  659. data/spec/mongoid/extensions/date_spec.rb +58 -140
  660. data/spec/mongoid/extensions/date_time_spec.rb +32 -69
  661. data/spec/mongoid/extensions/decimal128_spec.rb +2 -0
  662. data/spec/mongoid/extensions/false_class_spec.rb +3 -1
  663. data/spec/mongoid/extensions/float_spec.rb +66 -73
  664. data/spec/mongoid/extensions/hash_spec.rb +138 -3
  665. data/spec/mongoid/extensions/integer_spec.rb +61 -63
  666. data/spec/mongoid/extensions/module_spec.rb +2 -0
  667. data/spec/mongoid/extensions/nil_class_spec.rb +2 -0
  668. data/spec/mongoid/extensions/object_id_spec.rb +2 -0
  669. data/spec/mongoid/extensions/object_spec.rb +13 -24
  670. data/spec/mongoid/extensions/range_spec.rb +257 -54
  671. data/spec/mongoid/extensions/regexp_spec.rb +60 -33
  672. data/spec/mongoid/extensions/set_spec.rb +108 -0
  673. data/spec/mongoid/extensions/string_spec.rb +111 -50
  674. data/spec/mongoid/extensions/stringified_symbol_spec.rb +84 -0
  675. data/spec/mongoid/extensions/symbol_spec.rb +20 -25
  676. data/spec/mongoid/extensions/time_spec.rb +668 -106
  677. data/spec/mongoid/extensions/time_with_zone_spec.rb +57 -83
  678. data/spec/mongoid/extensions/true_class_spec.rb +3 -1
  679. data/spec/mongoid/extensions_spec.rb +16 -2
  680. data/spec/mongoid/factory_spec.rb +347 -27
  681. data/spec/mongoid/fields/foreign_key_spec.rb +2 -0
  682. data/spec/mongoid/fields/localized_spec.rb +86 -41
  683. data/spec/mongoid/fields/standard_spec.rb +2 -0
  684. data/spec/mongoid/fields_spec.rb +912 -114
  685. data/spec/mongoid/findable_spec.rb +520 -64
  686. data/spec/mongoid/indexable/specification_spec.rb +4 -2
  687. data/spec/mongoid/indexable_spec.rb +87 -32
  688. data/spec/mongoid/inspectable_spec.rb +39 -2
  689. data/spec/mongoid/interceptable_spec.rb +972 -98
  690. data/spec/mongoid/interceptable_spec_models.rb +307 -0
  691. data/spec/mongoid/loggable_spec.rb +2 -0
  692. data/spec/mongoid/matcher/extract_attribute_data/numeric_keys.yml +104 -0
  693. data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +239 -0
  694. data/spec/mongoid/matcher/extract_attribute_spec.rb +36 -0
  695. data/spec/mongoid/mongoizable_spec.rb +285 -0
  696. data/spec/mongoid/persistable/creatable_spec.rb +114 -29
  697. data/spec/mongoid/persistable/deletable_spec.rb +300 -18
  698. data/spec/mongoid/persistable/destroyable_spec.rb +228 -18
  699. data/spec/mongoid/persistable/incrementable_spec.rb +60 -7
  700. data/spec/mongoid/persistable/logical_spec.rb +56 -3
  701. data/spec/mongoid/persistable/poppable_spec.rb +55 -3
  702. data/spec/mongoid/persistable/pullable_spec.rb +108 -6
  703. data/spec/mongoid/persistable/pushable_spec.rb +163 -7
  704. data/spec/mongoid/persistable/renamable_spec.rb +54 -2
  705. data/spec/mongoid/persistable/savable_spec.rb +284 -25
  706. data/spec/mongoid/persistable/settable_spec.rb +91 -8
  707. data/spec/mongoid/persistable/unsettable_spec.rb +55 -3
  708. data/spec/mongoid/persistable/updatable_spec.rb +63 -49
  709. data/spec/mongoid/persistable/upsertable_spec.rb +93 -3
  710. data/spec/mongoid/persistable_spec.rb +85 -9
  711. data/spec/mongoid/persistence_context_spec.rb +59 -58
  712. data/spec/mongoid/positional_spec.rb +2 -0
  713. data/spec/mongoid/query_cache_middleware_spec.rb +50 -0
  714. data/spec/mongoid/query_cache_spec.rb +410 -95
  715. data/spec/mongoid/relations/proxy_spec.rb +9 -7
  716. data/spec/mongoid/reloadable_spec.rb +381 -26
  717. data/spec/mongoid/scopable_spec.rb +193 -38
  718. data/spec/mongoid/selectable_spec.rb +8 -6
  719. data/spec/mongoid/serializable_spec.rb +148 -38
  720. data/spec/mongoid/shardable_models.rb +75 -0
  721. data/spec/mongoid/shardable_spec.rb +239 -34
  722. data/spec/mongoid/stateful_spec.rb +153 -9
  723. data/spec/mongoid/tasks/database_rake_spec.rb +89 -13
  724. data/spec/mongoid/tasks/database_spec.rb +130 -1
  725. data/spec/mongoid/threaded_spec.rb +4 -2
  726. data/spec/mongoid/timestamps/created/short_spec.rb +3 -1
  727. data/spec/mongoid/timestamps/created_spec.rb +3 -1
  728. data/spec/mongoid/timestamps/timeless_spec.rb +4 -2
  729. data/spec/mongoid/timestamps/updated/short_spec.rb +5 -3
  730. data/spec/mongoid/timestamps/updated_spec.rb +5 -3
  731. data/spec/mongoid/timestamps_spec.rb +400 -10
  732. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  733. data/spec/mongoid/touchable_spec.rb +568 -33
  734. data/spec/mongoid/touchable_spec_models.rb +59 -0
  735. data/spec/mongoid/traversable_spec.rb +1145 -1
  736. data/spec/mongoid/validatable/associated_spec.rb +15 -30
  737. data/spec/mongoid/validatable/format_spec.rb +2 -0
  738. data/spec/mongoid/validatable/length_spec.rb +2 -0
  739. data/spec/mongoid/validatable/numericality_spec.rb +2 -0
  740. data/spec/mongoid/validatable/presence_spec.rb +28 -22
  741. data/spec/mongoid/validatable/uniqueness_spec.rb +159 -103
  742. data/spec/mongoid/validatable_spec.rb +5 -3
  743. data/spec/mongoid/warnings_spec.rb +35 -0
  744. data/spec/mongoid_spec.rb +36 -10
  745. data/spec/rails/controller_extension/controller_runtime_spec.rb +5 -3
  746. data/spec/rails/mongoid_spec.rb +8 -18
  747. data/spec/shared/LICENSE +20 -0
  748. data/spec/shared/bin/get-mongodb-download-url +17 -0
  749. data/spec/shared/bin/s3-copy +45 -0
  750. data/spec/shared/bin/s3-upload +69 -0
  751. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  752. data/spec/shared/lib/mrss/cluster_config.rb +231 -0
  753. data/spec/shared/lib/mrss/constraints.rb +378 -0
  754. data/spec/shared/lib/mrss/docker_runner.rb +298 -0
  755. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  756. data/spec/shared/lib/mrss/event_subscriber.rb +210 -0
  757. data/spec/shared/lib/mrss/lite_constraints.rb +238 -0
  758. data/spec/shared/lib/mrss/server_version_registry.rb +113 -0
  759. data/spec/shared/lib/mrss/session_registry.rb +69 -0
  760. data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
  761. data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
  762. data/spec/shared/lib/mrss/utils.rb +37 -0
  763. data/spec/shared/share/Dockerfile.erb +321 -0
  764. data/spec/shared/share/haproxy-1.conf +16 -0
  765. data/spec/shared/share/haproxy-2.conf +17 -0
  766. data/spec/shared/shlib/config.sh +27 -0
  767. data/spec/shared/shlib/distro.sh +74 -0
  768. data/spec/shared/shlib/server.sh +416 -0
  769. data/spec/shared/shlib/set_env.sh +169 -0
  770. data/spec/spec_helper.rb +44 -66
  771. data/spec/support/authorization.rb +2 -0
  772. data/spec/support/client_registry.rb +9 -0
  773. data/spec/support/constraints.rb +45 -69
  774. data/spec/support/expectations.rb +21 -3
  775. data/spec/support/helpers.rb +11 -0
  776. data/spec/support/immutable_ids.rb +118 -0
  777. data/spec/support/macros.rb +109 -0
  778. data/spec/{app → support}/models/account.rb +3 -1
  779. data/spec/{app → support}/models/acolyte.rb +2 -0
  780. data/spec/{app → support}/models/actor.rb +3 -1
  781. data/spec/support/models/actress.rb +4 -0
  782. data/spec/{app → support}/models/address.rb +6 -0
  783. data/spec/{app → support}/models/address_component.rb +2 -0
  784. data/spec/{app → support}/models/address_number.rb +2 -0
  785. data/spec/{app → support}/models/agency.rb +2 -0
  786. data/spec/{app → support}/models/agent.rb +2 -0
  787. data/spec/{app → support}/models/album.rb +2 -0
  788. data/spec/{app → support}/models/alert.rb +2 -0
  789. data/spec/{app → support}/models/animal.rb +2 -0
  790. data/spec/{app → support}/models/answer.rb +2 -0
  791. data/spec/{app → support}/models/appointment.rb +2 -0
  792. data/spec/support/models/armrest.rb +9 -0
  793. data/spec/{app → support}/models/article.rb +2 -0
  794. data/spec/{app → support}/models/artist.rb +4 -1
  795. data/spec/{app → support}/models/artwork.rb +2 -0
  796. data/spec/support/models/audible_sound.rb +3 -0
  797. data/spec/{app → support}/models/audio.rb +2 -0
  798. data/spec/support/models/augmentation.rb +25 -0
  799. data/spec/{app → support}/models/author.rb +2 -0
  800. data/spec/{app → support}/models/baby.rb +2 -0
  801. data/spec/{app → support}/models/band.rb +10 -0
  802. data/spec/{app → support}/models/bar.rb +2 -0
  803. data/spec/{app → support}/models/basic.rb +2 -0
  804. data/spec/support/models/bed.rb +3 -0
  805. data/spec/{app → support}/models/big_palette.rb +2 -0
  806. data/spec/{app → support}/models/birthday.rb +2 -0
  807. data/spec/support/models/bolt.rb +7 -0
  808. data/spec/{app → support}/models/bomb.rb +2 -0
  809. data/spec/{app → support}/models/book.rb +3 -0
  810. data/spec/{app → support}/models/breed.rb +2 -0
  811. data/spec/{app → support}/models/browser.rb +3 -1
  812. data/spec/{app → support}/models/building.rb +4 -0
  813. data/spec/{app → support}/models/building_address.rb +2 -0
  814. data/spec/{app → support}/models/bus.rb +2 -0
  815. data/spec/{app → support}/models/business.rb +2 -0
  816. data/spec/{app → support}/models/callback_test.rb +2 -0
  817. data/spec/{app → support}/models/canvas.rb +3 -1
  818. data/spec/support/models/car.rb +3 -0
  819. data/spec/{app → support}/models/cat.rb +2 -0
  820. data/spec/support/models/catalog.rb +24 -0
  821. data/spec/{app → support}/models/category.rb +2 -0
  822. data/spec/{app → support}/models/child.rb +2 -0
  823. data/spec/{app → support}/models/child_doc.rb +5 -3
  824. data/spec/{app → support}/models/church.rb +2 -0
  825. data/spec/{app → support}/models/circle.rb +2 -0
  826. data/spec/{app → support}/models/circuit.rb +2 -0
  827. data/spec/support/models/circus.rb +12 -0
  828. data/spec/{app → support}/models/code.rb +4 -0
  829. data/spec/support/models/coding/pull_request.rb +11 -0
  830. data/spec/support/models/coding.rb +3 -0
  831. data/spec/{app → support}/models/comment.rb +2 -0
  832. data/spec/{app → support}/models/company.rb +2 -0
  833. data/spec/{app → support}/models/consumption_period.rb +2 -0
  834. data/spec/{app → support}/models/contextable_item.rb +2 -0
  835. data/spec/{app → support}/models/contractor.rb +2 -0
  836. data/spec/{app → support}/models/cookie.rb +2 -0
  837. data/spec/{app → support}/models/country_code.rb +4 -0
  838. data/spec/{app → support}/models/courier_job.rb +2 -0
  839. data/spec/support/models/cover.rb +10 -0
  840. data/spec/support/models/crate.rb +12 -0
  841. data/spec/support/models/customer.rb +10 -0
  842. data/spec/support/models/customer_address.rb +11 -0
  843. data/spec/support/models/deed.rb +7 -0
  844. data/spec/{app → support}/models/definition.rb +2 -0
  845. data/spec/support/models/delegating_patient.rb +15 -0
  846. data/spec/{app → support}/models/description.rb +2 -0
  847. data/spec/{app → support}/models/dictionary.rb +8 -0
  848. data/spec/{app → support}/models/division.rb +2 -0
  849. data/spec/{app → support}/models/doctor.rb +2 -0
  850. data/spec/{app → support}/models/dog.rb +2 -0
  851. data/spec/{app → support}/models/dokument.rb +2 -0
  852. data/spec/{app → support}/models/draft.rb +2 -0
  853. data/spec/{app → support}/models/dragon.rb +2 -0
  854. data/spec/{app → support}/models/driver.rb +3 -1
  855. data/spec/{app → support}/models/drug.rb +2 -0
  856. data/spec/{app → support}/models/dungeon.rb +2 -0
  857. data/spec/{app → support}/models/edit.rb +2 -0
  858. data/spec/{app → support}/models/email.rb +2 -0
  859. data/spec/{app → support}/models/employer.rb +2 -0
  860. data/spec/{app → support}/models/entry.rb +2 -0
  861. data/spec/support/models/eraser.rb +3 -0
  862. data/spec/{app → support}/models/even.rb +2 -0
  863. data/spec/{app → support}/models/event.rb +2 -0
  864. data/spec/{app → support}/models/exhibition.rb +2 -0
  865. data/spec/{app → support}/models/exhibitor.rb +2 -0
  866. data/spec/{app → support}/models/explosion.rb +2 -0
  867. data/spec/{app → support}/models/eye.rb +2 -0
  868. data/spec/{app → support}/models/eye_bowl.rb +2 -0
  869. data/spec/{app → support}/models/face.rb +2 -0
  870. data/spec/support/models/fanatic.rb +8 -0
  871. data/spec/{app → support}/models/favorite.rb +2 -0
  872. data/spec/{app → support}/models/filesystem.rb +2 -0
  873. data/spec/{app → support}/models/fire_hydrant.rb +2 -0
  874. data/spec/{app → support}/models/firefox.rb +2 -0
  875. data/spec/{app → support}/models/fish.rb +2 -0
  876. data/spec/{app → support}/models/folder.rb +2 -0
  877. data/spec/{app → support}/models/folder_item.rb +2 -0
  878. data/spec/{app → support}/models/fruits.rb +2 -0
  879. data/spec/{app → support}/models/game.rb +2 -0
  880. data/spec/{app → support}/models/ghost.rb +2 -0
  881. data/spec/support/models/guitar.rb +4 -0
  882. data/spec/support/models/hole.rb +12 -0
  883. data/spec/{app → support}/models/home.rb +2 -0
  884. data/spec/{app → support}/models/house.rb +2 -0
  885. data/spec/{app → support}/models/html_writer.rb +2 -0
  886. data/spec/{app → support}/models/id_key.rb +2 -0
  887. data/spec/support/models/idnodef.rb +7 -0
  888. data/spec/{app → support}/models/image.rb +2 -0
  889. data/spec/{app → support}/models/implant.rb +11 -0
  890. data/spec/support/models/instrument.rb +8 -0
  891. data/spec/{app → support}/models/item.rb +3 -1
  892. data/spec/{app → support}/models/jar.rb +2 -0
  893. data/spec/{app → support}/models/kaleidoscope.rb +2 -0
  894. data/spec/{app → support}/models/kangaroo.rb +3 -1
  895. data/spec/{app → support}/models/label.rb +6 -1
  896. data/spec/{app → support}/models/language.rb +2 -0
  897. data/spec/{app → support}/models/lat_lng.rb +2 -0
  898. data/spec/{app → support}/models/league.rb +2 -0
  899. data/spec/support/models/learner.rb +4 -0
  900. data/spec/{app → support}/models/line_item.rb +2 -0
  901. data/spec/{app → support}/models/location.rb +2 -0
  902. data/spec/{app → support}/models/login.rb +2 -0
  903. data/spec/{app → support}/models/manufacturer.rb +2 -0
  904. data/spec/{app → support}/models/meat.rb +2 -0
  905. data/spec/{app → support}/models/membership.rb +3 -0
  906. data/spec/{app → support}/models/message.rb +2 -0
  907. data/spec/{app → support}/models/minim.rb +0 -1
  908. data/spec/{app → support}/models/mixed_drink.rb +2 -0
  909. data/spec/support/models/mop.rb +24 -0
  910. data/spec/{app → support}/models/movie.rb +2 -0
  911. data/spec/support/models/my_hash.rb +4 -0
  912. data/spec/{app → support}/models/name.rb +12 -0
  913. data/spec/support/models/name_only.rb +8 -0
  914. data/spec/{app → support}/models/node.rb +2 -0
  915. data/spec/{app → support}/models/note.rb +2 -0
  916. data/spec/support/models/nut.rb +7 -0
  917. data/spec/{app → support}/models/odd.rb +2 -0
  918. data/spec/support/models/order.rb +12 -0
  919. data/spec/{app → support}/models/ordered_post.rb +3 -1
  920. data/spec/{app → support}/models/ordered_preference.rb +2 -0
  921. data/spec/{app → support}/models/oscar.rb +2 -0
  922. data/spec/support/models/other_owner_object.rb +4 -0
  923. data/spec/{app → support}/models/override.rb +2 -0
  924. data/spec/{app → support}/models/ownable.rb +2 -0
  925. data/spec/{app → support}/models/owner.rb +4 -0
  926. data/spec/{app → support}/models/pack.rb +2 -0
  927. data/spec/{app → support}/models/page.rb +2 -0
  928. data/spec/{app → support}/models/page_question.rb +2 -0
  929. data/spec/{app → support}/models/palette.rb +3 -1
  930. data/spec/{app → support}/models/parent.rb +2 -0
  931. data/spec/{app → support}/models/parent_doc.rb +2 -0
  932. data/spec/support/models/passport.rb +22 -0
  933. data/spec/{app → support}/models/patient.rb +2 -0
  934. data/spec/{app → support}/models/pdf_writer.rb +2 -0
  935. data/spec/support/models/pencil.rb +3 -0
  936. data/spec/{app → support}/models/person.rb +23 -1
  937. data/spec/{app → support}/models/pet.rb +2 -0
  938. data/spec/{app → support}/models/pet_owner.rb +2 -0
  939. data/spec/{app → support}/models/phone.rb +5 -1
  940. data/spec/support/models/piano.rb +4 -0
  941. data/spec/{app → support}/models/pizza.rb +2 -0
  942. data/spec/{app → support}/models/player.rb +4 -0
  943. data/spec/{app → support}/models/post.rb +2 -0
  944. data/spec/{app → support}/models/post_genre.rb +2 -0
  945. data/spec/support/models/powerup.rb +25 -0
  946. data/spec/{app → support}/models/preference.rb +2 -0
  947. data/spec/{app → support}/models/princess.rb +2 -0
  948. data/spec/{app → support}/models/product.rb +3 -0
  949. data/spec/support/models/profile.rb +17 -0
  950. data/spec/{app → support}/models/pronunciation.rb +2 -0
  951. data/spec/{app → support}/models/pub.rb +2 -0
  952. data/spec/support/models/publication/encyclopedia.rb +11 -0
  953. data/spec/support/models/publication/review.rb +13 -0
  954. data/spec/support/models/publication.rb +4 -0
  955. data/spec/{app → support}/models/purchase.rb +2 -0
  956. data/spec/support/models/purchased_item.rb +10 -0
  957. data/spec/support/models/purse.rb +9 -0
  958. data/spec/{app → support}/models/question.rb +2 -0
  959. data/spec/{app → support}/models/quiz.rb +2 -0
  960. data/spec/{app → support}/models/rating.rb +2 -0
  961. data/spec/{app → support}/models/record.rb +2 -0
  962. data/spec/{app → support}/models/registry.rb +3 -0
  963. data/spec/{app → support}/models/role.rb +2 -0
  964. data/spec/{app → support}/models/root_category.rb +2 -0
  965. data/spec/{app → support}/models/sandwich.rb +2 -0
  966. data/spec/{app → support}/models/scheduler.rb +2 -0
  967. data/spec/support/models/school.rb +14 -0
  968. data/spec/support/models/scribe.rb +7 -0
  969. data/spec/support/models/sealer.rb +7 -0
  970. data/spec/support/models/seat.rb +24 -0
  971. data/spec/{app → support}/models/seo.rb +2 -0
  972. data/spec/support/models/series.rb +7 -0
  973. data/spec/{app → support}/models/server.rb +2 -0
  974. data/spec/{app → support}/models/service.rb +2 -0
  975. data/spec/{app → support}/models/shape.rb +4 -2
  976. data/spec/{app → support}/models/shelf.rb +2 -0
  977. data/spec/support/models/shield.rb +18 -0
  978. data/spec/{app → support}/models/shipment_address.rb +2 -0
  979. data/spec/{app → support}/models/shipping_container.rb +2 -0
  980. data/spec/{app → support}/models/shipping_pack.rb +2 -0
  981. data/spec/support/models/shirt.rb +11 -0
  982. data/spec/{app → support}/models/shop.rb +2 -0
  983. data/spec/{app → support}/models/short_agent.rb +2 -0
  984. data/spec/{app → support}/models/short_quiz.rb +2 -0
  985. data/spec/{app → support}/models/simple.rb +2 -0
  986. data/spec/{app → support}/models/slave.rb +2 -0
  987. data/spec/{app → support}/models/song.rb +2 -0
  988. data/spec/{app → support}/models/sound.rb +2 -0
  989. data/spec/support/models/spacer.rb +7 -0
  990. data/spec/{app → support}/models/square.rb +2 -0
  991. data/spec/{app → support}/models/staff.rb +2 -0
  992. data/spec/{app → support}/models/store_as_dup_test1.rb +2 -0
  993. data/spec/{app → support}/models/store_as_dup_test2.rb +2 -0
  994. data/spec/{app → support}/models/strategy.rb +2 -0
  995. data/spec/support/models/student.rb +14 -0
  996. data/spec/{app → support}/models/sub_item.rb +2 -0
  997. data/spec/{app → support}/models/subscription.rb +2 -0
  998. data/spec/{app → support}/models/survey.rb +2 -0
  999. data/spec/{app → support}/models/symptom.rb +2 -0
  1000. data/spec/support/models/system_role.rb +7 -0
  1001. data/spec/{app → support}/models/tag.rb +2 -0
  1002. data/spec/{app → support}/models/target.rb +2 -0
  1003. data/spec/{app → support}/models/template.rb +2 -0
  1004. data/spec/{app → support}/models/thing.rb +2 -0
  1005. data/spec/support/models/threadlocker.rb +7 -0
  1006. data/spec/{app → support}/models/title.rb +2 -0
  1007. data/spec/{app → support}/models/tool.rb +4 -2
  1008. data/spec/{app → support}/models/topping.rb +2 -0
  1009. data/spec/support/models/toy.rb +9 -0
  1010. data/spec/{app → support}/models/track.rb +2 -0
  1011. data/spec/{app → support}/models/translation.rb +2 -0
  1012. data/spec/{app → support}/models/tree.rb +2 -0
  1013. data/spec/support/models/truck.rb +7 -0
  1014. data/spec/{app → support}/models/user.rb +2 -0
  1015. data/spec/{app → support}/models/user_account.rb +2 -0
  1016. data/spec/{app → support}/models/validation_callback.rb +2 -0
  1017. data/spec/support/models/vehicle.rb +18 -0
  1018. data/spec/{app → support}/models/version.rb +2 -0
  1019. data/spec/{app → support}/models/vertex.rb +3 -1
  1020. data/spec/{app → support}/models/vet_visit.rb +2 -0
  1021. data/spec/{app → support}/models/video.rb +2 -0
  1022. data/spec/support/models/video_game.rb +3 -0
  1023. data/spec/support/models/washer.rb +7 -0
  1024. data/spec/support/models/weapon.rb +25 -0
  1025. data/spec/{app → support}/models/wiki_page.rb +3 -0
  1026. data/spec/{app → support}/models/word.rb +2 -0
  1027. data/spec/{app → support}/models/word_origin.rb +2 -0
  1028. data/spec/{app → support}/models/writer.rb +4 -2
  1029. data/spec/support/schema_maps/schema_map_aws.json +17 -0
  1030. data/spec/support/schema_maps/schema_map_aws_key_alt_names.json +12 -0
  1031. data/spec/support/schema_maps/schema_map_azure.json +17 -0
  1032. data/spec/support/schema_maps/schema_map_azure_key_alt_names.json +12 -0
  1033. data/spec/support/schema_maps/schema_map_gcp.json +17 -0
  1034. data/spec/support/schema_maps/schema_map_gcp_key_alt_names.json +12 -0
  1035. data/spec/support/schema_maps/schema_map_kmip.json +17 -0
  1036. data/spec/support/schema_maps/schema_map_kmip_key_alt_names.json +12 -0
  1037. data/spec/support/schema_maps/schema_map_local.json +18 -0
  1038. data/spec/support/schema_maps/schema_map_local_key_alt_names.json +12 -0
  1039. data/spec/support/shared/time.rb +53 -0
  1040. data/spec/support/spec_config.rb +30 -5
  1041. data.tar.gz.sig +0 -0
  1042. metadata +1249 -749
  1043. metadata.gz.sig +0 -0
  1044. data/lib/mongoid/criteria/queryable/forwardable.rb +0 -65
  1045. data/lib/mongoid/errors/eager_load.rb +0 -22
  1046. data/lib/mongoid/errors/invalid_value.rb +0 -16
  1047. data/lib/mongoid/matchable/all.rb +0 -27
  1048. data/lib/mongoid/matchable/and.rb +0 -30
  1049. data/lib/mongoid/matchable/default.rb +0 -72
  1050. data/lib/mongoid/matchable/elem_match.rb +0 -34
  1051. data/lib/mongoid/matchable/eq.rb +0 -22
  1052. data/lib/mongoid/matchable/exists.rb +0 -23
  1053. data/lib/mongoid/matchable/gt.rb +0 -23
  1054. data/lib/mongoid/matchable/gte.rb +0 -23
  1055. data/lib/mongoid/matchable/in.rb +0 -24
  1056. data/lib/mongoid/matchable/lt.rb +0 -23
  1057. data/lib/mongoid/matchable/lte.rb +0 -23
  1058. data/lib/mongoid/matchable/ne.rb +0 -21
  1059. data/lib/mongoid/matchable/nin.rb +0 -22
  1060. data/lib/mongoid/matchable/nor.rb +0 -37
  1061. data/lib/mongoid/matchable/or.rb +0 -33
  1062. data/lib/mongoid/matchable/regexp.rb +0 -27
  1063. data/lib/mongoid/matchable/size.rb +0 -21
  1064. data/lib/support/ruby_version.rb +0 -26
  1065. data/spec/app/models/actress.rb +0 -2
  1066. data/spec/app/models/augmentation.rb +0 -11
  1067. data/spec/app/models/bed.rb +0 -1
  1068. data/spec/app/models/car.rb +0 -1
  1069. data/spec/app/models/circus.rb +0 -7
  1070. data/spec/app/models/eraser.rb +0 -1
  1071. data/spec/app/models/learner.rb +0 -2
  1072. data/spec/app/models/my_hash.rb +0 -2
  1073. data/spec/app/models/other_owner_object.rb +0 -2
  1074. data/spec/app/models/passport.rb +0 -5
  1075. data/spec/app/models/pencil.rb +0 -1
  1076. data/spec/app/models/powerup.rb +0 -11
  1077. data/spec/app/models/profile.rb +0 -5
  1078. data/spec/app/models/series.rb +0 -4
  1079. data/spec/app/models/truck.rb +0 -3
  1080. data/spec/app/models/vehicle.rb +0 -11
  1081. data/spec/app/models/video_game.rb +0 -1
  1082. data/spec/app/models/weapon.rb +0 -11
  1083. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -58
  1084. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -58
  1085. data/spec/mongoid/criteria/queryable/forwardable_spec.rb +0 -87
  1086. data/spec/mongoid/matchable/all_spec.rb +0 -31
  1087. data/spec/mongoid/matchable/and_spec.rb +0 -187
  1088. data/spec/mongoid/matchable/default_spec.rb +0 -130
  1089. data/spec/mongoid/matchable/elem_match_spec.rb +0 -106
  1090. data/spec/mongoid/matchable/eq_spec.rb +0 -48
  1091. data/spec/mongoid/matchable/exists_spec.rb +0 -57
  1092. data/spec/mongoid/matchable/gt_spec.rb +0 -86
  1093. data/spec/mongoid/matchable/gte_spec.rb +0 -84
  1094. data/spec/mongoid/matchable/in_spec.rb +0 -49
  1095. data/spec/mongoid/matchable/lt_spec.rb +0 -85
  1096. data/spec/mongoid/matchable/lte_spec.rb +0 -85
  1097. data/spec/mongoid/matchable/ne_spec.rb +0 -46
  1098. data/spec/mongoid/matchable/nin_spec.rb +0 -48
  1099. data/spec/mongoid/matchable/nor_spec.rb +0 -209
  1100. data/spec/mongoid/matchable/or_spec.rb +0 -131
  1101. data/spec/mongoid/matchable/regexp_spec.rb +0 -59
  1102. data/spec/mongoid/matchable/size_spec.rb +0 -25
  1103. data/spec/mongoid/matchable_spec.rb +0 -853
  1104. data/spec/support/cluster_config.rb +0 -158
  1105. /data/spec/{app → support}/models/array_field.rb +0 -0
  1106. /data/spec/{app → support}/models/store_as_dup_test3.rb +0 -0
  1107. /data/spec/{app → support}/models/store_as_dup_test4.rb +0 -0
  1108. /data/spec/{app → support}/models/updatable.rb +0 -0
@@ -1,10 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Mongoid::Fields do
4
-
5
- before(:all) do
6
- Mongoid.use_activesupport_time_zone = false
7
- end
6
+ config_override :use_activesupport_time_zone, false
8
7
 
9
8
  describe "#\{field}_translations" do
10
9
 
@@ -15,18 +14,15 @@ describe Mongoid::Fields do
15
14
  context "when the field is localized" do
16
15
 
17
16
  context "when translations exist" do
17
+ with_default_i18n_configs
18
18
 
19
19
  before do
20
+ I18n.locale = :en
20
21
  product.description = "test"
21
- I18n.enforce_available_locales = false
22
- ::I18n.locale = :de
22
+ I18n.locale = :de
23
23
  product.description = "The best"
24
24
  end
25
25
 
26
- after do
27
- ::I18n.locale = :en
28
- end
29
-
30
26
  let(:translations) do
31
27
  product.description_translations
32
28
  end
@@ -107,7 +103,7 @@ describe Mongoid::Fields do
107
103
  context "when saving the new translations" do
108
104
 
109
105
  before do
110
- product.save
106
+ product.save!
111
107
  end
112
108
 
113
109
  it "persists the changes" do
@@ -118,7 +114,7 @@ describe Mongoid::Fields do
118
114
 
119
115
  before do
120
116
  product.description_translations = { "en" => "overwritten" }
121
- product.save
117
+ product.save!
122
118
  end
123
119
 
124
120
  it "persists the changes" do
@@ -149,7 +145,7 @@ describe Mongoid::Fields do
149
145
  context "when saving the new translations" do
150
146
 
151
147
  before do
152
- dictionary.save
148
+ dictionary.save!
153
149
  end
154
150
 
155
151
  it "persists the changes" do
@@ -162,7 +158,7 @@ describe Mongoid::Fields do
162
158
 
163
159
  before do
164
160
  dictionary.description_translations = { "en" => "overwritten" }
165
- dictionary.save
161
+ dictionary.save!
166
162
  end
167
163
 
168
164
  it "persists the changes" do
@@ -319,7 +315,7 @@ describe Mongoid::Fields do
319
315
  end
320
316
 
321
317
  it "converts to Mongoid::Boolean" do
322
- expect(klass.field(:test, type: Boolean).type).to be(Mongoid::Boolean)
318
+ expect(klass.field(:test, type: Mongoid::Boolean).type).to be(Mongoid::Boolean)
323
319
  end
324
320
  end
325
321
 
@@ -394,6 +390,22 @@ describe Mongoid::Fields do
394
390
  it "converts :time to Time" do
395
391
  expect(klass.field(:test, type: :time).type).to be(Time)
396
392
  end
393
+
394
+ context 'when using an unknown symbol' do
395
+ it 'raises InvalidFieldType' do
396
+ lambda do
397
+ klass.field(:test, type: :bogus)
398
+ end.should raise_error(Mongoid::Errors::InvalidFieldType, /defines a field 'test' with an unknown type value :bogus/)
399
+ end
400
+ end
401
+
402
+ context 'when using an unknown string' do
403
+ it 'raises InvalidFieldType' do
404
+ lambda do
405
+ klass.field(:test, type: 'bogus')
406
+ end.should raise_error(Mongoid::Errors::InvalidFieldType, /defines a field 'test' with an unknown type value "bogus"/)
407
+ end
408
+ end
397
409
  end
398
410
 
399
411
  context "when the options are valid" do
@@ -401,7 +413,7 @@ describe Mongoid::Fields do
401
413
  context "when the options are all standard" do
402
414
 
403
415
  before do
404
- Band.field :acceptable, type: Boolean
416
+ Band.field :acceptable, type: Mongoid::Boolean
405
417
  end
406
418
 
407
419
  after do
@@ -416,7 +428,7 @@ describe Mongoid::Fields do
416
428
  context "when a custom option is provided" do
417
429
 
418
430
  before do
419
- Band.field :acceptable, type: Boolean, custom: true
431
+ Band.field :acceptable, type: Mongoid::Boolean, custom: true
420
432
  end
421
433
 
422
434
  it "adds the field to the model" do
@@ -425,11 +437,49 @@ describe Mongoid::Fields do
425
437
  end
426
438
  end
427
439
 
440
+ context "when the Symbol type is used" do
441
+
442
+ before do
443
+ Mongoid::Warnings.class_eval do
444
+ @symbol_type_deprecated = false
445
+ end
446
+ end
447
+
448
+ after do
449
+ Label.fields.delete("should_warn")
450
+ end
451
+
452
+ it "warns that the BSON symbol type is deprecated" do
453
+ expect(Mongoid.logger).to receive(:warn)
454
+
455
+ Label.field :should_warn, type: Symbol
456
+ end
457
+
458
+ it "warns on first use of Symbol type only" do
459
+ expect(Mongoid.logger).to receive(:warn).once
460
+
461
+ Label.field :should_warn, type: Symbol
462
+ end
463
+
464
+ context 'when using Symbol field type in multiple classes' do
465
+ after do
466
+ Truck.fields.delete("should_warn")
467
+ end
468
+
469
+ it "warns on first use of Symbol type only" do
470
+ expect(Mongoid.logger).to receive(:warn).once
471
+
472
+ Label.field :should_warn, type: Symbol
473
+ Truck.field :should_warn, type: Symbol
474
+ end
475
+ end
476
+ end
477
+
428
478
  context "when the options are not valid" do
429
479
 
430
480
  it "raises an error" do
431
481
  expect {
432
- Band.field :unacceptable, bad: true
482
+ Label.field :unacceptable, bad: true
433
483
  }.to raise_error(Mongoid::Errors::InvalidFieldOption)
434
484
  end
435
485
  end
@@ -474,16 +524,13 @@ describe Mongoid::Fields do
474
524
  end
475
525
 
476
526
  context "when a single locale is set" do
527
+ with_default_i18n_configs
477
528
 
478
529
  before do
479
- ::I18n.locale = :de
530
+ I18n.locale = :de
480
531
  product.description = "The best"
481
532
  end
482
533
 
483
- after do
484
- ::I18n.locale = :en
485
- end
486
-
487
534
  let(:description) do
488
535
  product.description
489
536
  end
@@ -494,17 +541,15 @@ describe Mongoid::Fields do
494
541
  end
495
542
 
496
543
  context "when multiple locales are set" do
544
+ with_default_i18n_configs
497
545
 
498
546
  before do
547
+ I18n.locale = :end
499
548
  product.description = "Cheap drinks"
500
- ::I18n.locale = :de
549
+ I18n.locale = :de
501
550
  product.description = "Cheaper drinks"
502
551
  end
503
552
 
504
- after do
505
- ::I18n.locale = :en
506
- end
507
-
508
553
  let(:description) do
509
554
  product.description
510
555
  end
@@ -514,6 +559,49 @@ describe Mongoid::Fields do
514
559
  end
515
560
  end
516
561
  end
562
+
563
+ context 'when the field is declared as BSON::Decimal128' do
564
+ let(:document) { Mop.create!(decimal128_field: BSON::Decimal128.new(Math::PI.to_s)).reload }
565
+
566
+ shared_context 'BSON::Decimal128 is BigDecimal' do
567
+ it 'should return a BigDecimal' do
568
+ expect(document.decimal128_field).to be_a BigDecimal
569
+ end
570
+ end
571
+
572
+ shared_context 'BSON::Decimal128 is BSON::Decimal128' do
573
+ it 'should return a BSON::Decimal128' do
574
+ expect(document.decimal128_field).to be_a BSON::Decimal128
575
+ end
576
+ end
577
+
578
+ it 'is declared as BSON::Decimal128' do
579
+ expect(Mop.fields['decimal128_field'].type).to be == BSON::Decimal128
580
+ end
581
+
582
+ context 'when BSON version <= 4' do
583
+ max_bson_version '4.99.99'
584
+ it_behaves_like 'BSON::Decimal128 is BSON::Decimal128'
585
+ end
586
+
587
+ context 'when BSON version >= 5' do
588
+ min_bson_version '5.0.0'
589
+
590
+ context 'when allow_bson5_decimal128 is false' do
591
+ config_override :allow_bson5_decimal128, false
592
+ it_behaves_like 'BSON::Decimal128 is BigDecimal'
593
+ end
594
+
595
+ context 'when allow_bson5_decimal128 is true' do
596
+ config_override :allow_bson5_decimal128, true
597
+ it_behaves_like 'BSON::Decimal128 is BSON::Decimal128'
598
+ end
599
+
600
+ context 'when allow_bson5_decimal128 is default' do
601
+ it_behaves_like 'BSON::Decimal128 is BigDecimal'
602
+ end
603
+ end
604
+ end
517
605
  end
518
606
 
519
607
  describe "#getter_before_type_cast" do
@@ -531,8 +619,144 @@ describe Mongoid::Fields do
531
619
  context "when the attribute has been assigned" do
532
620
 
533
621
  it "returns the attribute before type cast" do
534
- person.age = "old"
535
- expect(person.age_before_type_cast).to eq("old")
622
+ person.age = "42"
623
+ expect(person.age_before_type_cast).to eq("42")
624
+ end
625
+ end
626
+
627
+ context "when reloading" do
628
+
629
+ let(:product) do
630
+ Product.create!(price: '1')
631
+ end
632
+
633
+ before do
634
+ product.reload
635
+ end
636
+
637
+ it "resets the attributes_before_type_cast to the attributes hash" do
638
+ expect(product.attributes_before_type_cast).to eq(product.attributes)
639
+ end
640
+
641
+ it "the *_before_type_cast method returns the demongoized value" do
642
+ expect(product.price_before_type_cast).to eq(1)
643
+ end
644
+ end
645
+
646
+ context "when reloading and writing a demongoizable value" do
647
+
648
+ let(:product) do
649
+ Product.create!.tap do |product|
650
+ Product.collection.update_one({ _id: product.id }, { :$set => { price: '1' }})
651
+ end
652
+ end
653
+
654
+ before do
655
+ product.reload
656
+ end
657
+
658
+ it "resets the attributes_before_type_cast to the attributes hash" do
659
+ expect(product.attributes_before_type_cast).to eq(product.attributes)
660
+ end
661
+
662
+ it "the *_before_type_cast method returns the mongoized value" do
663
+ expect(product.price_before_type_cast).to eq('1')
664
+ end
665
+ end
666
+
667
+ context "when reading from the db" do
668
+
669
+ let(:product) do
670
+ Product.create!(price: '1')
671
+ end
672
+
673
+ let(:from_db) do
674
+ Product.find(product.id)
675
+ end
676
+
677
+ it "resets the attributes_before_type_cast to the attributes hash" do
678
+ expect(from_db.attributes_before_type_cast).to eq(from_db.attributes)
679
+ end
680
+
681
+ it "the *_before_type_cast method returns the demongoized value" do
682
+ expect(from_db.price_before_type_cast).to eq(1)
683
+ end
684
+ end
685
+
686
+ context "when reading from the db after writing a demongoizable value" do
687
+
688
+ let(:product) do
689
+ Product.create!.tap do |product|
690
+ Product.collection.update_one({ _id: product.id }, { :$set => { price: '1' }})
691
+ end
692
+ end
693
+
694
+ let(:from_db) do
695
+ Product.find(product.id)
696
+ end
697
+
698
+ it "resets the attributes_before_type_cast to the attributes hash" do
699
+ expect(from_db.attributes_before_type_cast).to eq(from_db.attributes)
700
+ end
701
+
702
+ it "the *_before_type_cast method returns the mongoized value" do
703
+ expect(from_db.price_before_type_cast).to eq('1')
704
+ end
705
+ end
706
+
707
+ context "when making a new model" do
708
+
709
+ context "when using new with no options" do
710
+ let(:product) { Product.new }
711
+
712
+ it "sets the attributes_before_type_cast to the attributes hash" do
713
+ expect(product.attributes_before_type_cast).to eq(product.attributes)
714
+ end
715
+ end
716
+
717
+ context "when using new with options" do
718
+ let(:product) { Product.new(price: '1') }
719
+
720
+ let(:abtc) do
721
+ product.attributes.merge('price' => '1')
722
+ end
723
+
724
+ it "has the attributes before type cast" do
725
+ expect(product.attributes_before_type_cast).to eq(abtc)
726
+ end
727
+ end
728
+
729
+ context "when persisting the model" do
730
+ let(:product) { Product.new(price: '1') }
731
+
732
+ let(:abtc) do
733
+ product.attributes.merge('price' => '1')
734
+ end
735
+
736
+ before do
737
+ expect(product.attributes_before_type_cast).to eq(abtc)
738
+ product.save!
739
+ end
740
+
741
+ it "resets the attributes_before_type_cast to the attributes" do
742
+ expect(product.attributes_before_type_cast).to eq(product.attributes)
743
+ end
744
+ end
745
+
746
+ context "when using create! without options" do
747
+ let(:product) { Product.create! }
748
+
749
+ it "resets the attributes_before_type_cast to the attributes" do
750
+ expect(product.attributes_before_type_cast).to eq(product.attributes)
751
+ end
752
+ end
753
+
754
+ context "when using create! with options" do
755
+ let(:product) { Product.create!(price: '1') }
756
+
757
+ it "resets the attributes_before_type_cast to the attributes" do
758
+ expect(product.attributes_before_type_cast).to eq(product.attributes)
759
+ end
536
760
  end
537
761
  end
538
762
  end
@@ -580,14 +804,14 @@ describe Mongoid::Fields do
580
804
 
581
805
  before do
582
806
  product.stores = [ "kadewe", "karstadt" ]
583
- product.save
807
+ product.save!
584
808
  end
585
809
 
586
810
  context "when setting the value to nil" do
587
811
 
588
812
  before do
589
813
  product.stores = nil
590
- product.save
814
+ product.save!
591
815
  end
592
816
 
593
817
  it "allows the set" do
@@ -599,7 +823,7 @@ describe Mongoid::Fields do
599
823
 
600
824
  before do
601
825
  product.stores = [ "kadewe", nil ]
602
- product.save
826
+ product.save!
603
827
  end
604
828
 
605
829
  it "allows the set of nil values" do
@@ -615,7 +839,7 @@ describe Mongoid::Fields do
615
839
 
616
840
  before do
617
841
  product.stores = [ "karstadt", "kadewe" ]
618
- product.save
842
+ product.save!
619
843
  end
620
844
 
621
845
  it "reverses the values" do
@@ -646,16 +870,13 @@ describe Mongoid::Fields do
646
870
  end
647
871
 
648
872
  context "when a locale is set" do
873
+ with_default_i18n_configs
649
874
 
650
875
  before do
651
- ::I18n.locale = :de
876
+ I18n.locale = :de
652
877
  product.description = "Cheaper drinks"
653
878
  end
654
879
 
655
- after do
656
- ::I18n.locale = :en
657
- end
658
-
659
880
  let(:description) do
660
881
  product.attributes["description"]
661
882
  end
@@ -666,17 +887,15 @@ describe Mongoid::Fields do
666
887
  end
667
888
 
668
889
  context "when having multiple locales" do
890
+ with_default_i18n_configs
669
891
 
670
892
  before do
893
+ I18n.locale = :en
671
894
  product.description = "Cheap drinks"
672
- ::I18n.locale = :de
895
+ I18n.locale = :de
673
896
  product.description = "Cheaper drinks"
674
897
  end
675
898
 
676
- after do
677
- ::I18n.locale = :en
678
- end
679
-
680
899
  let(:description) do
681
900
  product.attributes["description"]
682
901
  end
@@ -688,6 +907,22 @@ describe Mongoid::Fields do
688
907
  end
689
908
  end
690
909
  end
910
+
911
+ context "when the field needs to be mongoized" do
912
+
913
+ before do
914
+ product.price = "1"
915
+ product.save!
916
+ end
917
+
918
+ it "mongoizes the value" do
919
+ expect(product.price).to eq(1)
920
+ end
921
+
922
+ it "stores the value in the mongoized form" do
923
+ expect(product.attributes_before_type_cast["price"]).to eq(1)
924
+ end
925
+ end
691
926
  end
692
927
 
693
928
  describe "#defaults" do
@@ -792,7 +1027,8 @@ describe Mongoid::Fields do
792
1027
  end
793
1028
 
794
1029
  it "does not return subclass defaults" do
795
- expect(shape.pre_processed_defaults).to eq([ "_id", "x", "y", "_type" ])
1030
+ expect(shape.pre_processed_defaults).to eq([ "_id", "x", "y" ])
1031
+ expect(shape.post_processed_defaults).to eq([ "_type" ])
796
1032
  end
797
1033
  end
798
1034
 
@@ -803,7 +1039,8 @@ describe Mongoid::Fields do
803
1039
  end
804
1040
 
805
1041
  it "has the parent and child defaults" do
806
- expect(circle.pre_processed_defaults).to eq([ "_id", "x", "y", "_type", "radius" ])
1042
+ expect(circle.pre_processed_defaults).to eq([ "_id", "x", "y", "radius" ])
1043
+ expect(circle.post_processed_defaults).to eq([ "_type" ])
807
1044
  end
808
1045
  end
809
1046
  end
@@ -822,32 +1059,30 @@ describe Mongoid::Fields do
822
1059
  it "raises an error" do
823
1060
  expect {
824
1061
  Person.field(meth)
825
- }.to raise_error(Mongoid::Errors::InvalidField)
1062
+ }.to raise_error(Mongoid::Errors::InvalidField, /Defining a field named '#{meth}' is not allowed/)
826
1063
  end
827
1064
  end
828
1065
  end
829
1066
  end
830
1067
 
831
1068
  context "when field already exist and validate_duplicate is enable" do
1069
+ context 'when exception is enabled' do
1070
+ config_override :duplicate_fields_exception, true
832
1071
 
833
- before do
834
- Mongoid.duplicate_fields_exception = true
835
- end
836
-
837
- after do
838
- Mongoid.duplicate_fields_exception = false
839
- end
840
-
841
- it "raises an error" do
842
- expect {
843
- Person.field(:title)
844
- }.to raise_error(Mongoid::Errors::InvalidField)
1072
+ it "raises an error" do
1073
+ expect {
1074
+ Person.field(:title)
1075
+ }.to raise_error(Mongoid::Errors::InvalidField)
1076
+ end
845
1077
  end
846
1078
 
847
- it "doesn't raise an error" do
848
- expect {
849
- Class.new(Person)
850
- }.to_not raise_error
1079
+ context 'when exception is disabled' do
1080
+ config_override :duplicate_fields_exception, false
1081
+ it "doesn't raise an error" do
1082
+ expect {
1083
+ Class.new(Person)
1084
+ }.to_not raise_error
1085
+ end
851
1086
  end
852
1087
  end
853
1088
 
@@ -862,14 +1097,7 @@ describe Mongoid::Fields do
862
1097
  end
863
1098
 
864
1099
  context "when reading the field" do
865
-
866
- before do
867
- Time.zone = "Berlin"
868
- end
869
-
870
- after do
871
- Time.zone = nil
872
- end
1100
+ time_zone_override "Berlin"
873
1101
 
874
1102
  it "performs the necessary time conversions" do
875
1103
  expect(person.lunch_time.to_s).to eq(time.getlocal.to_s)
@@ -947,11 +1175,11 @@ describe Mongoid::Fields do
947
1175
  end
948
1176
 
949
1177
  before do
950
- Person.field :aliased, as: :alias, type: Boolean, overwrite: true
1178
+ Person.field :aliased, as: :alias, type: Mongoid::Boolean, overwrite: true
951
1179
  end
952
1180
 
953
1181
  it "uses the alias to write the attribute" do
954
- (person.alias = expect(true)).to be true
1182
+ expect(person.alias = true).to be true
955
1183
  end
956
1184
 
957
1185
  it "uses the alias to read the attribute" do
@@ -963,7 +1191,7 @@ describe Mongoid::Fields do
963
1191
  end
964
1192
 
965
1193
  it "uses the name to write the attribute" do
966
- (person.aliased = expect(true)).to be true
1194
+ expect(person.aliased = true).to be true
967
1195
  end
968
1196
 
969
1197
  it "uses the name to read the attribute" do
@@ -1075,6 +1303,10 @@ describe Mongoid::Fields do
1075
1303
  it "does not return subclass fields" do
1076
1304
  expect(shape.fields.keys).to_not include("radius")
1077
1305
  end
1306
+
1307
+ it 'includes _type field' do
1308
+ expect(shape.fields.keys).to include("_type")
1309
+ end
1078
1310
  end
1079
1311
 
1080
1312
  context "on subclasses" do
@@ -1094,6 +1326,28 @@ describe Mongoid::Fields do
1094
1326
  it "includes the child fields" do
1095
1327
  expect(circle.fields.keys).to include("radius")
1096
1328
  end
1329
+
1330
+ it 'includes _type field' do
1331
+ expect(circle.fields.keys).to include("_type")
1332
+ end
1333
+ end
1334
+
1335
+ context "on new subclasses" do
1336
+ it "all subclasses get the discriminator key" do
1337
+ class DiscriminatorParent
1338
+ include Mongoid::Document
1339
+ end
1340
+
1341
+ class DiscriminatorChild1 < DiscriminatorParent
1342
+ end
1343
+
1344
+ class DiscriminatorChild2 < DiscriminatorParent
1345
+ end
1346
+
1347
+ expect(DiscriminatorParent.fields.keys).to include("_type")
1348
+ expect(DiscriminatorChild1.fields.keys).to include("_type")
1349
+ expect(DiscriminatorChild2.fields.keys).to include("_type")
1350
+ end
1097
1351
  end
1098
1352
  end
1099
1353
 
@@ -1166,71 +1420,147 @@ describe Mongoid::Fields do
1166
1420
 
1167
1421
  context "when a field is defined as a big decimal" do
1168
1422
 
1169
- let(:band) do
1170
- Band.new(name: "Tool")
1171
- end
1172
-
1173
- let(:decimal) do
1174
- BigDecimal("1000000.00")
1175
- end
1423
+ context 'when Mongoid.map_big_decimal_to_decimal128 is false' do
1424
+ config_override :map_big_decimal_to_decimal128, false
1176
1425
 
1177
- context "when setting to a big decimal" do
1178
-
1179
- before do
1180
- band.sales = decimal
1426
+ let(:band) do
1427
+ Band.new(name: "Tool")
1181
1428
  end
1182
1429
 
1183
- it "properly persists as a string" do
1184
- expect(band.attributes["sales"]).to eq(decimal.to_s)
1430
+ let(:decimal) do
1431
+ BigDecimal("1000000.00")
1185
1432
  end
1186
1433
 
1187
- it "returns the proper big decimal" do
1188
- expect(band.sales).to eq(decimal)
1434
+ context "when setting to a big decimal" do
1435
+
1436
+ before do
1437
+ band.sales = decimal
1438
+ end
1439
+
1440
+ it "properly persists as a string" do
1441
+ expect(band.attributes["sales"]).to eq(decimal.to_s)
1442
+ end
1443
+
1444
+ it "returns the proper big decimal" do
1445
+ expect(band.sales).to eq(decimal)
1446
+ end
1189
1447
  end
1190
- end
1191
1448
 
1192
- context "when setting to a string" do
1449
+ context "when setting to a string" do
1193
1450
 
1194
- before do
1195
- band.sales = decimal.to_s
1451
+ before do
1452
+ band.sales = decimal.to_s
1453
+ end
1454
+
1455
+ it "properly persists as a string" do
1456
+ expect(band.attributes["sales"]).to eq(decimal.to_s)
1457
+ end
1458
+
1459
+ it "returns the proper big decimal" do
1460
+ expect(band.sales).to eq(decimal)
1461
+ end
1196
1462
  end
1197
1463
 
1198
- it "properly persists as a string" do
1199
- expect(band.attributes["sales"]).to eq(decimal.to_s)
1464
+ context "when setting to an integer" do
1465
+
1466
+ before do
1467
+ band.sales = decimal.to_i
1468
+ end
1469
+
1470
+ it "properly persists as a string" do
1471
+ expect(band.attributes["sales"]).to eq("1000000")
1472
+ end
1473
+
1474
+ it "returns the proper big decimal" do
1475
+ expect(band.sales).to eq(decimal)
1476
+ end
1200
1477
  end
1201
1478
 
1202
- it "returns the proper big decimal" do
1203
- expect(band.sales).to eq(decimal)
1479
+ context "when setting to a float" do
1480
+
1481
+ before do
1482
+ band.sales = decimal.to_f
1483
+ end
1484
+
1485
+ it "properly persists as a string" do
1486
+ expect(band.attributes["sales"]).to eq(decimal.to_s)
1487
+ end
1488
+
1489
+ it "returns the proper big decimal" do
1490
+ expect(band.sales).to eq(decimal)
1491
+ end
1204
1492
  end
1205
1493
  end
1206
1494
 
1207
- context "when setting to an integer" do
1495
+ context 'when Mongoid.map_big_decimal_to_decimal128 is true' do
1496
+ config_override :map_big_decimal_to_decimal128, true
1208
1497
 
1209
- before do
1210
- band.sales = decimal.to_i
1498
+ let(:band) do
1499
+ Band.new(name: "Tool")
1211
1500
  end
1212
1501
 
1213
- it "properly persists as a string" do
1214
- expect(band.attributes["sales"]).to eq("1000000")
1502
+ let(:decimal) do
1503
+ BigDecimal("1000000.00")
1215
1504
  end
1216
1505
 
1217
- it "returns the proper big decimal" do
1218
- expect(band.sales).to eq(decimal)
1506
+ context "when setting to a big decimal" do
1507
+
1508
+ before do
1509
+ band.sales = decimal
1510
+ end
1511
+
1512
+ it "properly persists as a BSON::Decimal128" do
1513
+ expect(band.attributes["sales"]).to eq(BSON::Decimal128.new(decimal))
1514
+ end
1515
+
1516
+ it "returns the proper big decimal" do
1517
+ expect(band.sales).to eq(decimal)
1518
+ end
1219
1519
  end
1220
- end
1221
1520
 
1222
- context "when setting to a float" do
1521
+ context "when setting to a string" do
1223
1522
 
1224
- before do
1225
- band.sales = decimal.to_f
1523
+ before do
1524
+ band.sales = decimal.to_s
1525
+ end
1526
+
1527
+ it "persists as a BSON::Decimal128" do
1528
+ expect(band.attributes["sales"]).to eq(BSON::Decimal128.new(decimal.to_s))
1529
+ end
1530
+
1531
+ it "returns the proper big decimal" do
1532
+ expect(band.sales).to eq(decimal)
1533
+ end
1226
1534
  end
1227
1535
 
1228
- it "properly persists as a string" do
1229
- expect(band.attributes["sales"]).to eq(decimal.to_s)
1536
+ context "when setting to an integer" do
1537
+
1538
+ before do
1539
+ band.sales = decimal.to_i
1540
+ end
1541
+
1542
+ it "persists as a BSON::Decimal128" do
1543
+ expect(band.attributes["sales"]).to eq(BSON::Decimal128.new(decimal.to_i.to_s))
1544
+ end
1545
+
1546
+ it "returns the proper big decimal" do
1547
+ expect(band.sales).to eq(decimal)
1548
+ end
1230
1549
  end
1231
1550
 
1232
- it "returns the proper big decimal" do
1233
- expect(band.sales).to eq(decimal)
1551
+ context "when setting to a float" do
1552
+
1553
+ before do
1554
+ band.sales = decimal.to_f
1555
+ end
1556
+
1557
+ it "properly persists as a BSON::Decimal128" do
1558
+ expect(band.attributes["sales"]).to eq(BSON::Decimal128.new(decimal.to_f.to_s))
1559
+ end
1560
+
1561
+ it "returns the proper big decimal" do
1562
+ expect(band.sales).to eq(decimal)
1563
+ end
1234
1564
  end
1235
1565
  end
1236
1566
  end
@@ -1238,7 +1568,7 @@ describe Mongoid::Fields do
1238
1568
  context "when the field is a hash of arrays" do
1239
1569
 
1240
1570
  let(:person) do
1241
- Person.create
1571
+ Person.create!
1242
1572
  end
1243
1573
 
1244
1574
  let(:map) do
@@ -1252,7 +1582,7 @@ describe Mongoid::Fields do
1252
1582
  before do
1253
1583
  person.map = map
1254
1584
  person.map["stack1"].reverse!
1255
- person.save
1585
+ person.save!
1256
1586
  end
1257
1587
 
1258
1588
  it "properly updates the hash" do
@@ -1311,4 +1641,472 @@ describe Mongoid::Fields do
1311
1641
  end
1312
1642
  end
1313
1643
  end
1644
+
1645
+ describe '_type field' do
1646
+ context 'on parent class' do
1647
+ let(:shape) { Shape.new }
1648
+
1649
+ it 'is correctly set' do
1650
+ shape.attributes['_type'].should == 'Shape'
1651
+ end
1652
+ end
1653
+
1654
+ context 'on child class' do
1655
+ let(:circle) { Circle.new }
1656
+
1657
+ it 'is correctly set' do
1658
+ circle.attributes['_type'].should == 'Circle'
1659
+ end
1660
+ end
1661
+ end
1662
+
1663
+ describe '.database_field_name' do
1664
+
1665
+ shared_examples_for 'database_field_name' do
1666
+ subject { Person.database_field_name(key) }
1667
+
1668
+ context 'non-aliased field name' do
1669
+ let(:key) { 't' }
1670
+ it { is_expected.to eq 't' }
1671
+ end
1672
+
1673
+ context 'aliased field name' do
1674
+ let(:key) { 'test' }
1675
+ it { is_expected.to eq 't' }
1676
+ end
1677
+
1678
+ context 'non-aliased embeds one relation' do
1679
+ let(:key) { 'pass' }
1680
+ it { is_expected.to eq 'pass' }
1681
+ end
1682
+
1683
+ context 'aliased embeds one relation' do
1684
+ let(:key) { 'passport' }
1685
+ it { is_expected.to eq 'pass' }
1686
+ end
1687
+
1688
+ context 'non-aliased embeds many relation' do
1689
+ let(:key) { 'mobile_phones' }
1690
+ it { is_expected.to eq 'mobile_phones' }
1691
+ end
1692
+
1693
+ context 'aliased embeds many relation' do
1694
+ let(:key) { 'phones' }
1695
+ it { is_expected.to eq 'mobile_phones' }
1696
+ end
1697
+
1698
+ context 'non-aliased embeds one field' do
1699
+ let(:key) { 'pass.exp' }
1700
+ it { is_expected.to eq 'pass.exp' }
1701
+ end
1702
+
1703
+ context 'aliased embeds one field' do
1704
+ let(:key) { 'passport.expiration_date' }
1705
+ it { is_expected.to eq 'pass.exp' }
1706
+ end
1707
+
1708
+ context 'non-aliased embeds many field' do
1709
+ let(:key) { 'mobile_phones.landline' }
1710
+ it { is_expected.to eq 'mobile_phones.landline' }
1711
+ end
1712
+
1713
+ context 'aliased embeds many field' do
1714
+ let(:key) { 'phones.extension' }
1715
+ it { is_expected.to eq 'mobile_phones.ext' }
1716
+ end
1717
+
1718
+ context 'aliased multi-level embedded document' do
1719
+ let(:key) { 'phones.extension' }
1720
+ it { is_expected.to eq 'mobile_phones.ext' }
1721
+ end
1722
+
1723
+ context 'non-aliased multi-level embedded document' do
1724
+ let(:key) { 'phones.extension' }
1725
+ it { is_expected.to eq 'mobile_phones.ext' }
1726
+ end
1727
+
1728
+ context 'aliased multi-level embedded document field' do
1729
+ let(:key) { 'mobile_phones.country_code.code' }
1730
+ it { is_expected.to eq 'mobile_phones.country_code.code' }
1731
+ end
1732
+
1733
+ context 'non-aliased multi-level embedded document field' do
1734
+ let(:key) { 'phones.country_code.iso_alpha2_code' }
1735
+ it { is_expected.to eq 'mobile_phones.country_code.iso' }
1736
+ end
1737
+
1738
+ context 'when field is unknown' do
1739
+ let(:key) { 'shenanigans' }
1740
+ it { is_expected.to eq 'shenanigans' }
1741
+ end
1742
+
1743
+ context 'when embedded field is unknown' do
1744
+ let(:key) { 'phones.bamboozle' }
1745
+ it { is_expected.to eq 'mobile_phones.bamboozle' }
1746
+ end
1747
+
1748
+ context 'when multi-level embedded field is unknown' do
1749
+ let(:key) { 'phones.bamboozle.brouhaha' }
1750
+ it { is_expected.to eq 'mobile_phones.bamboozle.brouhaha' }
1751
+ end
1752
+ end
1753
+
1754
+ shared_examples_for 'pre-fix database_field_name' do
1755
+ subject { Person.database_field_name(key) }
1756
+
1757
+ context 'non-aliased field name' do
1758
+ let(:key) { 't' }
1759
+ it { is_expected.to eq 't' }
1760
+ end
1761
+
1762
+ context 'aliased field name' do
1763
+ let(:key) { 'test' }
1764
+ it { is_expected.to eq 't' }
1765
+ end
1766
+
1767
+ context 'non-aliased embeds one relation' do
1768
+ let(:key) { 'pass' }
1769
+ it { is_expected.to eq 'pass' }
1770
+ end
1771
+
1772
+ context 'aliased embeds one relation' do
1773
+ let(:key) { 'passport' }
1774
+ it { is_expected.to eq 'pass' }
1775
+ end
1776
+
1777
+ context 'non-aliased embeds many relation' do
1778
+ let(:key) { 'mobile_phones' }
1779
+ it { is_expected.to eq 'mobile_phones' }
1780
+ end
1781
+
1782
+ context 'aliased embeds many relation' do
1783
+ let(:key) { 'phones' }
1784
+ it { is_expected.to eq 'mobile_phones' }
1785
+ end
1786
+
1787
+ context 'non-aliased embeds one field' do
1788
+ let(:key) { 'pass.exp' }
1789
+ it { is_expected.to eq 'pass.exp' }
1790
+ end
1791
+
1792
+ context 'aliased embeds one field' do
1793
+ let(:key) { 'passport.expiration_date' }
1794
+ it { is_expected.to eq 'passport.expiration_date' }
1795
+ end
1796
+
1797
+ context 'non-aliased embeds many field' do
1798
+ let(:key) { 'mobile_phones.landline' }
1799
+ it { is_expected.to eq 'mobile_phones.landline' }
1800
+ end
1801
+
1802
+ context 'aliased embeds many field' do
1803
+ let(:key) { 'phones.extension' }
1804
+ it { is_expected.to eq 'phones.extension' }
1805
+ end
1806
+
1807
+ context 'aliased multi-level embedded document' do
1808
+ let(:key) { 'phones.extension' }
1809
+ it { is_expected.to eq 'phones.extension' }
1810
+ end
1811
+
1812
+ context 'non-aliased multi-level embedded document' do
1813
+ let(:key) { 'phones.extension' }
1814
+ it { is_expected.to eq 'phones.extension' }
1815
+ end
1816
+
1817
+ context 'aliased multi-level embedded document field' do
1818
+ let(:key) { 'mobile_phones.country_code.code' }
1819
+ it { is_expected.to eq 'mobile_phones.country_code.code' }
1820
+ end
1821
+
1822
+ context 'non-aliased multi-level embedded document field' do
1823
+ let(:key) { 'phones.country_code.iso_alpha2_code' }
1824
+ it { is_expected.to eq 'phones.country_code.iso_alpha2_code' }
1825
+ end
1826
+
1827
+ context 'when field is unknown' do
1828
+ let(:key) { 'shenanigans' }
1829
+ it { is_expected.to eq 'shenanigans' }
1830
+ end
1831
+
1832
+ context 'when embedded field is unknown' do
1833
+ let(:key) { 'phones.bamboozle' }
1834
+ it { is_expected.to eq 'phones.bamboozle' }
1835
+ end
1836
+
1837
+ context 'when multi-level embedded field is unknown' do
1838
+ let(:key) { 'phones.bamboozle.brouhaha' }
1839
+ it { is_expected.to eq 'phones.bamboozle.brouhaha' }
1840
+ end
1841
+ end
1842
+
1843
+ context "when the broken_alias_handling is not set" do
1844
+ config_override :broken_alias_handling, false
1845
+
1846
+ context 'given nil' do
1847
+ subject { Person.database_field_name(nil) }
1848
+ it { is_expected.to eq nil }
1849
+ end
1850
+
1851
+ context 'given an empty String' do
1852
+ subject { Person.database_field_name('') }
1853
+ it { is_expected.to eq nil }
1854
+ end
1855
+
1856
+ context 'given a String' do
1857
+ subject { Person.database_field_name(key.to_s) }
1858
+ it_behaves_like 'database_field_name'
1859
+ end
1860
+
1861
+ context 'given a Symbol' do
1862
+ subject { Person.database_field_name(key.to_sym) }
1863
+ it_behaves_like 'database_field_name'
1864
+ end
1865
+ end
1866
+
1867
+ context "when the broken_alias_handling is set" do
1868
+ config_override :broken_alias_handling, true
1869
+
1870
+ context 'given nil' do
1871
+ subject { Person.database_field_name(nil) }
1872
+ it { is_expected.to eq nil }
1873
+ end
1874
+
1875
+ context 'given an empty String' do
1876
+ subject { Person.database_field_name('') }
1877
+ it { is_expected.to eq "" }
1878
+ end
1879
+
1880
+ context 'given a String' do
1881
+ subject { Person.database_field_name(key.to_s) }
1882
+ it_behaves_like 'pre-fix database_field_name'
1883
+ end
1884
+
1885
+ context 'given a Symbol' do
1886
+ subject { Person.database_field_name(key.to_sym) }
1887
+ it_behaves_like 'pre-fix database_field_name'
1888
+ end
1889
+ end
1890
+
1891
+ context 'when getting the database field name of a belongs_to associations' do
1892
+ # These tests only apply when the flag is not set
1893
+ config_override :broken_alias_handling, false
1894
+
1895
+ context "when the broken_alias_handling is not set" do
1896
+ context "when the association is the last item" do
1897
+ let(:name) do
1898
+ Game.database_field_name("person")
1899
+ end
1900
+
1901
+ it "gets the alias" do
1902
+ expect(name).to eq("person_id")
1903
+ end
1904
+ end
1905
+
1906
+ context "when the association is not the last item" do
1907
+ let(:name) do
1908
+ Game.database_field_name("person.name")
1909
+ end
1910
+
1911
+ it "gets the alias" do
1912
+ expect(name).to eq("person.name")
1913
+ end
1914
+ end
1915
+ end
1916
+ end
1917
+ end
1918
+
1919
+ describe "#get_field" do
1920
+
1921
+ let(:klass) { Person }
1922
+ let(:field) { klass.cleanse_localized_field_names(field_name) }
1923
+
1924
+ context "when cleansing a field" do
1925
+ let(:field_name) { "employer_id" }
1926
+ it "returns the correct field name" do
1927
+ expect(field).to eq(field_name)
1928
+ end
1929
+ end
1930
+
1931
+ context "when cleansing a localized field" do
1932
+ let(:field_name) { "desc" }
1933
+ it "returns the correct field name" do
1934
+ expect(field).to eq(field_name)
1935
+ end
1936
+ end
1937
+
1938
+ context "when cleansing a translation field" do
1939
+ let(:field_name) { "desc_translations" }
1940
+ it "returns the correct field name" do
1941
+ expect(field).to eq("desc")
1942
+ end
1943
+ end
1944
+
1945
+ context "when cleansing an existing translation field" do
1946
+ let(:field_name) { "localized_translations" }
1947
+ it "returns the correct field name" do
1948
+ expect(field).to eq(field_name)
1949
+ end
1950
+ end
1951
+
1952
+ context "when cleansing an existing translation field with a _translations" do
1953
+ let(:field_name) { "localized_translations_translations" }
1954
+ it "returns the correct field name" do
1955
+ expect(field).to eq("localized_translations")
1956
+ end
1957
+ end
1958
+
1959
+ context "when cleansing dotted translation field" do
1960
+ config_override :broken_alias_handling, false
1961
+ let(:field_name) { "passport.name_translations.asd" }
1962
+ it "returns the correct field name" do
1963
+ expect(field).to eq("pass.name.asd")
1964
+ end
1965
+ end
1966
+
1967
+ context "when cleansing dotted translation field as a symbol" do
1968
+ config_override :broken_alias_handling, false
1969
+ let(:field_name) { "passport.name_translations.asd".to_sym }
1970
+ it "returns the correct field name" do
1971
+ expect(field).to eq("pass.name.asd")
1972
+ end
1973
+ end
1974
+
1975
+ context "when cleansing dotted existing translation field" do
1976
+ config_override :broken_alias_handling, false
1977
+ let(:field_name) { "passport.localized_translations.asd" }
1978
+ it "returns the correct field name" do
1979
+ expect(field).to eq("pass.localized_translations.asd")
1980
+ end
1981
+ end
1982
+
1983
+ context "when cleansing aliased dotted translation field" do
1984
+ let(:field_name) { "pass.name_translations.asd" }
1985
+ it "returns the correct field name" do
1986
+ expect(field).to eq("pass.name.asd")
1987
+ end
1988
+ end
1989
+ end
1990
+
1991
+ describe "localize: :present" do
1992
+
1993
+ let(:product) do
1994
+ Product.new
1995
+ end
1996
+
1997
+ context "when assigning a non blank value" do
1998
+
1999
+ before do
2000
+ product.title = "hello"
2001
+ end
2002
+
2003
+ it "assigns the value" do
2004
+ expect(product.title).to eq("hello")
2005
+ end
2006
+
2007
+ it "populates the translations hash" do
2008
+ expect(product.title_translations).to eq({ "en" => "hello" })
2009
+ end
2010
+ end
2011
+
2012
+ context "when assigning an empty string" do
2013
+ with_default_i18n_configs
2014
+
2015
+ before do
2016
+ I18n.locale = :en
2017
+ product.title = "hello"
2018
+ I18n.locale = :de
2019
+ product.title = "hello there!"
2020
+ product.title = ""
2021
+ end
2022
+
2023
+ it "assigns the value" do
2024
+ expect(product.title).to eq(nil)
2025
+ end
2026
+
2027
+ it "populates the translations hash" do
2028
+ expect(product.title_translations).to eq({ "en" => "hello" })
2029
+ end
2030
+ end
2031
+
2032
+ context "when assigning nil" do
2033
+ with_default_i18n_configs
2034
+
2035
+ before do
2036
+ I18n.locale = :en
2037
+ product.title = "hello"
2038
+ I18n.locale = :de
2039
+ product.title = "hello there!"
2040
+ product.title = nil
2041
+ end
2042
+
2043
+ it "assigns the value" do
2044
+ expect(product.title).to eq(nil)
2045
+ end
2046
+
2047
+ it "populates the translations hash" do
2048
+ expect(product.title_translations).to eq({ "en" => "hello" })
2049
+ end
2050
+ end
2051
+
2052
+ context "when assigning an empty array" do
2053
+ with_default_i18n_configs
2054
+
2055
+ before do
2056
+ I18n.locale = :en
2057
+ product.title = "hello"
2058
+ I18n.locale = :de
2059
+ product.title = "hello there!"
2060
+ product.title = []
2061
+ end
2062
+
2063
+ it "assigns the value" do
2064
+ expect(product.title).to eq(nil)
2065
+ end
2066
+
2067
+ it "populates the translations hash" do
2068
+ expect(product.title_translations).to eq({ "en" => "hello" })
2069
+ end
2070
+ end
2071
+
2072
+ context "when assigning an empty string first" do
2073
+ with_default_i18n_configs
2074
+
2075
+ before do
2076
+ product.title = ""
2077
+ end
2078
+
2079
+ it "assigns the value" do
2080
+ expect(product.title).to eq(nil)
2081
+ end
2082
+
2083
+ it "populates the translations hash" do
2084
+ expect(product.title_translations).to eq({})
2085
+ end
2086
+ end
2087
+
2088
+ context "when assigning an empty string with only one translation" do
2089
+ with_default_i18n_configs
2090
+
2091
+ before do
2092
+ product.title = "Hello"
2093
+ product.title = ""
2094
+ product.save!
2095
+ end
2096
+
2097
+ let(:from_db) { Product.first }
2098
+
2099
+ it "assigns the value" do
2100
+ expect(product.title).to eq(nil)
2101
+ end
2102
+
2103
+ it "populates the translations hash" do
2104
+ expect(product.title_translations).to eq({})
2105
+ end
2106
+
2107
+ it "round trips an empty hash" do
2108
+ expect(from_db.title_translations).to eq({})
2109
+ end
2110
+ end
2111
+ end
1314
2112
  end