mongoid 7.5.3 → 8.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (295) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +3 -3
  4. data/lib/config/locales/en.yml +46 -30
  5. data/lib/mongoid/association/accessors.rb +32 -3
  6. data/lib/mongoid/association/bindable.rb +48 -0
  7. data/lib/mongoid/association/builders.rb +4 -2
  8. data/lib/mongoid/association/eager_loadable.rb +29 -7
  9. data/lib/mongoid/association/embedded/batchable.rb +28 -5
  10. data/lib/mongoid/association/embedded/embedded_in/binding.rb +24 -2
  11. data/lib/mongoid/association/embedded/embedded_in.rb +2 -1
  12. data/lib/mongoid/association/embedded/embeds_many/binding.rb +1 -0
  13. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +1 -1
  14. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +40 -18
  15. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +18 -4
  16. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +21 -2
  17. data/lib/mongoid/association/macros.rb +2 -1
  18. data/lib/mongoid/association/many.rb +5 -0
  19. data/lib/mongoid/association/nested/many.rb +2 -1
  20. data/lib/mongoid/association/proxy.rb +12 -0
  21. data/lib/mongoid/association/referenced/auto_save.rb +3 -2
  22. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -0
  23. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
  24. data/lib/mongoid/association/referenced/belongs_to.rb +1 -1
  25. data/lib/mongoid/association/referenced/counter_cache.rb +8 -8
  26. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +64 -11
  27. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +4 -1
  28. data/lib/mongoid/association/referenced/has_many/enumerable.rb +10 -18
  29. data/lib/mongoid/association/referenced/has_many/proxy.rb +12 -9
  30. data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
  31. data/lib/mongoid/association/referenced/has_one/proxy.rb +8 -11
  32. data/lib/mongoid/association/referenced/syncable.rb +2 -2
  33. data/lib/mongoid/association/relatable.rb +38 -4
  34. data/lib/mongoid/attributes/processing.rb +9 -2
  35. data/lib/mongoid/attributes.rb +30 -27
  36. data/lib/mongoid/cacheable.rb +2 -2
  37. data/lib/mongoid/changeable.rb +37 -2
  38. data/lib/mongoid/clients/options.rb +4 -0
  39. data/lib/mongoid/clients/sessions.rb +2 -14
  40. data/lib/mongoid/config.rb +15 -11
  41. data/lib/mongoid/contextual/aggregable/memory.rb +23 -15
  42. data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
  43. data/lib/mongoid/contextual/map_reduce.rb +2 -2
  44. data/lib/mongoid/contextual/memory.rb +55 -28
  45. data/lib/mongoid/contextual/mongo.rb +173 -262
  46. data/lib/mongoid/contextual/none.rb +33 -15
  47. data/lib/mongoid/copyable.rb +32 -8
  48. data/lib/mongoid/criteria/includable.rb +24 -20
  49. data/lib/mongoid/criteria/marshalable.rb +10 -2
  50. data/lib/mongoid/criteria/queryable/extensions/array.rb +2 -15
  51. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +25 -4
  52. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
  53. data/lib/mongoid/criteria/queryable/extensions/date.rb +6 -1
  54. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +6 -1
  55. data/lib/mongoid/criteria/queryable/extensions/hash.rb +0 -16
  56. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  57. data/lib/mongoid/criteria/queryable/extensions/object.rb +2 -1
  58. data/lib/mongoid/criteria/queryable/extensions/range.rb +13 -5
  59. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +1 -1
  60. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +3 -1
  61. data/lib/mongoid/criteria/queryable/extensions/time.rb +6 -1
  62. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +6 -1
  63. data/lib/mongoid/criteria/queryable/optional.rb +3 -9
  64. data/lib/mongoid/criteria/queryable/options.rb +1 -1
  65. data/lib/mongoid/criteria/queryable/selectable.rb +2 -24
  66. data/lib/mongoid/criteria/queryable/selector.rb +89 -4
  67. data/lib/mongoid/criteria/queryable/smash.rb +39 -6
  68. data/lib/mongoid/criteria/queryable.rb +11 -6
  69. data/lib/mongoid/criteria.rb +1 -28
  70. data/lib/mongoid/deprecable.rb +36 -0
  71. data/lib/mongoid/deprecation.rb +25 -0
  72. data/lib/mongoid/document.rb +88 -33
  73. data/lib/mongoid/equality.rb +4 -4
  74. data/lib/mongoid/errors/document_not_found.rb +6 -2
  75. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  76. data/lib/mongoid/errors/invalid_field.rb +5 -1
  77. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  78. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -1
  79. data/lib/mongoid/errors.rb +2 -2
  80. data/lib/mongoid/extensions/array.rb +8 -6
  81. data/lib/mongoid/extensions/big_decimal.rb +29 -10
  82. data/lib/mongoid/extensions/binary.rb +42 -0
  83. data/lib/mongoid/extensions/boolean.rb +8 -2
  84. data/lib/mongoid/extensions/date.rb +26 -20
  85. data/lib/mongoid/extensions/date_time.rb +1 -1
  86. data/lib/mongoid/extensions/float.rb +4 -5
  87. data/lib/mongoid/extensions/hash.rb +12 -5
  88. data/lib/mongoid/extensions/integer.rb +4 -5
  89. data/lib/mongoid/extensions/object.rb +2 -0
  90. data/lib/mongoid/extensions/range.rb +41 -10
  91. data/lib/mongoid/extensions/regexp.rb +11 -4
  92. data/lib/mongoid/extensions/set.rb +11 -4
  93. data/lib/mongoid/extensions/string.rb +2 -13
  94. data/lib/mongoid/extensions/symbol.rb +3 -14
  95. data/lib/mongoid/extensions/time.rb +27 -16
  96. data/lib/mongoid/extensions/time_with_zone.rb +1 -2
  97. data/lib/mongoid/extensions.rb +1 -0
  98. data/lib/mongoid/factory.rb +42 -7
  99. data/lib/mongoid/fields/foreign_key.rb +7 -0
  100. data/lib/mongoid/fields/validators/macro.rb +3 -9
  101. data/lib/mongoid/fields.rb +49 -7
  102. data/lib/mongoid/findable.rb +21 -16
  103. data/lib/mongoid/indexable/specification.rb +1 -1
  104. data/lib/mongoid/indexable/validators/options.rb +4 -1
  105. data/lib/mongoid/interceptable.rb +69 -9
  106. data/lib/mongoid/persistable/creatable.rb +14 -5
  107. data/lib/mongoid/persistable/updatable.rb +12 -5
  108. data/lib/mongoid/persistence_context.rb +8 -42
  109. data/lib/mongoid/query_cache.rb +6 -258
  110. data/lib/mongoid/railties/controller_runtime.rb +1 -1
  111. data/lib/mongoid/reloadable.rb +7 -3
  112. data/lib/mongoid/scopable.rb +9 -11
  113. data/lib/mongoid/selectable.rb +1 -2
  114. data/lib/mongoid/shardable.rb +11 -35
  115. data/lib/mongoid/stateful.rb +27 -1
  116. data/lib/mongoid/timestamps/created.rb +1 -1
  117. data/lib/mongoid/timestamps/updated.rb +1 -1
  118. data/lib/mongoid/touchable.rb +2 -3
  119. data/lib/mongoid/traversable.rb +1 -0
  120. data/lib/mongoid/validatable/uniqueness.rb +2 -1
  121. data/lib/mongoid/version.rb +1 -1
  122. data/lib/mongoid/warnings.rb +3 -4
  123. data/lib/mongoid.rb +1 -0
  124. data/spec/config/mongoid.yml +16 -0
  125. data/spec/integration/app_spec.rb +8 -12
  126. data/spec/integration/associations/belongs_to_spec.rb +18 -0
  127. data/spec/integration/associations/embedded_spec.rb +15 -0
  128. data/spec/integration/associations/embeds_many_spec.rb +15 -2
  129. data/spec/integration/associations/embeds_one_spec.rb +18 -0
  130. data/spec/integration/associations/foreign_key_spec.rb +9 -0
  131. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +21 -0
  132. data/spec/integration/associations/has_one_spec.rb +97 -1
  133. data/spec/integration/associations/scope_option_spec.rb +1 -1
  134. data/spec/integration/callbacks_models.rb +95 -1
  135. data/spec/integration/callbacks_spec.rb +226 -4
  136. data/spec/integration/criteria/range_spec.rb +95 -1
  137. data/spec/integration/discriminator_key_spec.rb +115 -76
  138. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  139. data/spec/integration/i18n_fallbacks_spec.rb +1 -15
  140. data/spec/integration/matcher_examples_spec.rb +20 -13
  141. data/spec/integration/matcher_operator_data/type_decimal.yml +3 -2
  142. data/spec/integration/matcher_operator_spec.rb +3 -5
  143. data/spec/integration/persistence/range_field_spec.rb +350 -0
  144. data/spec/mongoid/association/counter_cache_spec.rb +1 -1
  145. data/spec/mongoid/association/depending_spec.rb +9 -9
  146. data/spec/mongoid/association/eager_spec.rb +2 -1
  147. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +2 -1
  148. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +54 -0
  149. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +69 -9
  150. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +112 -0
  151. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +198 -8
  152. data/spec/mongoid/association/embedded/embeds_many_models.rb +36 -0
  153. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +12 -0
  154. data/spec/mongoid/association/embedded/embeds_many_spec.rb +68 -0
  155. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +25 -0
  156. data/spec/mongoid/association/embedded/embeds_one_models.rb +19 -0
  157. data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -0
  158. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +2 -1
  159. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +54 -0
  160. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +15 -0
  161. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  162. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -2
  163. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +38 -5
  164. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +25 -0
  165. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +35 -2
  166. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +109 -0
  167. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +2 -56
  168. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +62 -13
  169. data/spec/mongoid/association/referenced/has_many_models.rb +3 -1
  170. data/spec/mongoid/association/referenced/has_many_spec.rb +25 -0
  171. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +2 -2
  172. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +107 -1
  173. data/spec/mongoid/association/referenced/has_one_models.rb +16 -0
  174. data/spec/mongoid/association/syncable_spec.rb +14 -0
  175. data/spec/mongoid/atomic/paths_spec.rb +0 -14
  176. data/spec/mongoid/attributes/nested_spec.rb +80 -11
  177. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  178. data/spec/mongoid/attributes/projector_spec.rb +1 -5
  179. data/spec/mongoid/attributes_spec.rb +480 -27
  180. data/spec/mongoid/cacheable_spec.rb +3 -3
  181. data/spec/mongoid/changeable_spec.rb +130 -13
  182. data/spec/mongoid/clients/factory_spec.rb +23 -30
  183. data/spec/mongoid/clients/sessions_spec.rb +0 -38
  184. data/spec/mongoid/clients_spec.rb +2 -2
  185. data/spec/mongoid/config_spec.rb +52 -14
  186. data/spec/mongoid/contextual/aggregable/memory_spec.rb +396 -158
  187. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  188. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  189. data/spec/mongoid/contextual/map_reduce_spec.rb +2 -16
  190. data/spec/mongoid/contextual/memory_spec.rb +521 -14
  191. data/spec/mongoid/contextual/mongo_spec.rb +566 -416
  192. data/spec/mongoid/contextual/none_spec.rb +11 -19
  193. data/spec/mongoid/copyable_spec.rb +451 -1
  194. data/spec/mongoid/criteria/findable_spec.rb +86 -210
  195. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  196. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  197. data/spec/mongoid/criteria/marshalable_spec.rb +18 -1
  198. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +7 -19
  199. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +134 -26
  200. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +11 -0
  201. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +11 -0
  202. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +0 -15
  203. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -7
  204. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +11 -0
  205. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +11 -0
  206. data/spec/mongoid/criteria/queryable/optional_spec.rb +0 -484
  207. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +50 -0
  208. data/spec/mongoid/criteria/queryable/selectable_spec.rb +77 -85
  209. data/spec/mongoid/criteria/queryable/selector_spec.rb +14 -2
  210. data/spec/mongoid/criteria_spec.rb +469 -1201
  211. data/spec/mongoid/document_fields_spec.rb +173 -24
  212. data/spec/mongoid/document_spec.rb +32 -41
  213. data/spec/mongoid/equality_spec.rb +12 -12
  214. data/spec/mongoid/errors/document_not_found_spec.rb +29 -2
  215. data/spec/mongoid/errors/invalid_field_spec.rb +1 -1
  216. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  217. data/spec/mongoid/errors/mongoid_error_spec.rb +3 -1
  218. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  219. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +1 -1
  220. data/spec/mongoid/extensions/array_spec.rb +16 -2
  221. data/spec/mongoid/extensions/big_decimal_spec.rb +697 -212
  222. data/spec/mongoid/extensions/binary_spec.rb +44 -9
  223. data/spec/mongoid/extensions/boolean_spec.rb +68 -82
  224. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +7 -3
  225. data/spec/mongoid/extensions/date_spec.rb +71 -1
  226. data/spec/mongoid/extensions/date_time_spec.rb +15 -9
  227. data/spec/mongoid/extensions/float_spec.rb +48 -76
  228. data/spec/mongoid/extensions/hash_spec.rb +30 -0
  229. data/spec/mongoid/extensions/integer_spec.rb +45 -66
  230. data/spec/mongoid/extensions/range_spec.rb +255 -54
  231. data/spec/mongoid/extensions/regexp_spec.rb +58 -33
  232. data/spec/mongoid/extensions/set_spec.rb +106 -0
  233. data/spec/mongoid/extensions/string_spec.rb +53 -25
  234. data/spec/mongoid/extensions/symbol_spec.rb +18 -25
  235. data/spec/mongoid/extensions/time_spec.rb +634 -66
  236. data/spec/mongoid/extensions/time_with_zone_spec.rb +17 -31
  237. data/spec/mongoid/factory_spec.rb +61 -1
  238. data/spec/mongoid/fields_spec.rb +321 -50
  239. data/spec/mongoid/findable_spec.rb +64 -29
  240. data/spec/mongoid/indexable/specification_spec.rb +2 -2
  241. data/spec/mongoid/indexable_spec.rb +16 -19
  242. data/spec/mongoid/interceptable_spec.rb +584 -5
  243. data/spec/mongoid/interceptable_spec_models.rb +235 -4
  244. data/spec/mongoid/matcher/extract_attribute_spec.rb +1 -5
  245. data/spec/mongoid/mongoizable_spec.rb +285 -0
  246. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  247. data/spec/mongoid/persistable/deletable_spec.rb +2 -2
  248. data/spec/mongoid/persistable/destroyable_spec.rb +2 -2
  249. data/spec/mongoid/persistable/upsertable_spec.rb +14 -0
  250. data/spec/mongoid/persistence_context_spec.rb +24 -0
  251. data/spec/mongoid/query_cache_middleware_spec.rb +0 -18
  252. data/spec/mongoid/query_cache_spec.rb +0 -154
  253. data/spec/mongoid/reloadable_spec.rb +35 -2
  254. data/spec/mongoid/scopable_spec.rb +36 -34
  255. data/spec/mongoid/shardable_models.rb +0 -14
  256. data/spec/mongoid/shardable_spec.rb +61 -153
  257. data/spec/mongoid/stateful_spec.rb +28 -0
  258. data/spec/mongoid/timestamps_spec.rb +390 -0
  259. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  260. data/spec/mongoid/touchable_spec.rb +116 -0
  261. data/spec/mongoid/touchable_spec_models.rb +12 -8
  262. data/spec/mongoid/traversable_spec.rb +4 -11
  263. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  264. data/spec/mongoid/validatable/uniqueness_spec.rb +60 -31
  265. data/spec/mongoid/warnings_spec.rb +35 -0
  266. data/spec/mongoid_spec.rb +1 -7
  267. data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
  268. data/spec/rails/mongoid_spec.rb +4 -16
  269. data/spec/shared/lib/mrss/event_subscriber.rb +5 -15
  270. data/spec/shared/lib/mrss/lite_constraints.rb +0 -8
  271. data/spec/shared/shlib/server.sh +5 -5
  272. data/spec/support/constraints.rb +24 -0
  273. data/spec/support/macros.rb +30 -0
  274. data/spec/support/models/augmentation.rb +12 -0
  275. data/spec/support/models/band.rb +3 -0
  276. data/spec/support/models/catalog.rb +24 -0
  277. data/spec/support/models/circus.rb +3 -0
  278. data/spec/support/models/fanatic.rb +8 -0
  279. data/spec/support/models/implant.rb +9 -0
  280. data/spec/support/models/label.rb +2 -0
  281. data/spec/support/models/passport.rb +9 -0
  282. data/spec/support/models/person.rb +1 -0
  283. data/spec/support/models/player.rb +2 -0
  284. data/spec/support/models/powerup.rb +12 -0
  285. data/spec/support/models/registry.rb +1 -0
  286. data/spec/support/models/school.rb +14 -0
  287. data/spec/support/models/shield.rb +18 -0
  288. data/spec/support/models/student.rb +14 -0
  289. data/spec/support/models/weapon.rb +12 -0
  290. data.tar.gz.sig +0 -0
  291. metadata +669 -638
  292. metadata.gz.sig +0 -0
  293. data/lib/mongoid/errors/eager_load.rb +0 -23
  294. data/lib/mongoid/errors/invalid_value.rb +0 -17
  295. data/spec/mongoid/errors/eager_load_spec.rb +0 -31
@@ -830,10 +830,6 @@ describe Mongoid::Contextual::Memory do
830
830
  expect(context.send(method, 1)).to eq([ hobrecht ])
831
831
  end
832
832
 
833
- it "returns the matching document when passing deprecated options" do
834
- expect(context.send(method, id_sort: :none)).to eq(hobrecht)
835
- end
836
-
837
833
  context 'when there is a collation on the criteria' do
838
834
 
839
835
  let(:criteria) do
@@ -1086,10 +1082,6 @@ describe Mongoid::Contextual::Memory do
1086
1082
  expect(context.last(1)).to eq([ friedel ])
1087
1083
  end
1088
1084
 
1089
- it "returns the matching document when passing deprecated options" do
1090
- expect(context.last(id_sort: :none)).to eq(friedel)
1091
- end
1092
-
1093
1085
  context 'when there is a collation on the criteria' do
1094
1086
 
1095
1087
  let(:criteria) do
@@ -1352,7 +1344,7 @@ describe Mongoid::Contextual::Memory do
1352
1344
  Band.create!(name: "Photek", likes: 1)
1353
1345
  end
1354
1346
 
1355
- let(:maniacs) do
1347
+ let!(:maniacs) do
1356
1348
  Band.create!(name: "10,000 Maniacs", likes: 1, sales: "1E2")
1357
1349
  end
1358
1350
 
@@ -1678,9 +1670,12 @@ describe Mongoid::Contextual::Memory do
1678
1670
  Band.where(name: maniacs.name).pluck(:sales)
1679
1671
  end
1680
1672
 
1681
- it "demongoizes the field" do
1682
- expect(plucked.first).to be_a(BigDecimal)
1683
- expect(plucked.first).to eq(BigDecimal("1E2"))
1673
+ with_config_values :map_big_decimal_to_decimal128, true, false do
1674
+
1675
+ it "demongoizes the field" do
1676
+ expect(plucked.first).to be_a(BigDecimal)
1677
+ expect(plucked.first).to eq(BigDecimal("1E2"))
1678
+ end
1684
1679
  end
1685
1680
  end
1686
1681
 
@@ -1690,7 +1685,7 @@ describe Mongoid::Contextual::Memory do
1690
1685
 
1691
1686
  let(:plucked) do
1692
1687
  Band.where(_id: band.id).tap do |crit|
1693
- crit.documents = [band]
1688
+ crit.documents = [ band ]
1694
1689
  end.pluck("label.sales")
1695
1690
  end
1696
1691
 
@@ -1716,7 +1711,7 @@ describe Mongoid::Contextual::Memory do
1716
1711
 
1717
1712
  let(:plucked) do
1718
1713
  Band.where(_id: band.id).tap do |crit|
1719
- crit.documents = band
1714
+ crit.documents = [ band ]
1720
1715
  end.pluck("label.qwerty")
1721
1716
  end
1722
1717
 
@@ -1750,6 +1745,518 @@ describe Mongoid::Contextual::Memory do
1750
1745
  end
1751
1746
  end
1752
1747
 
1748
+ describe "#pick" do
1749
+
1750
+ let(:depeche) do
1751
+ Band.create!(name: "Depeche Mode", likes: 3)
1752
+ end
1753
+
1754
+ let(:tool) do
1755
+ Band.create!(name: "Tool", likes: 3)
1756
+ end
1757
+
1758
+ let(:criteria) do
1759
+ Band.all.tap do |crit|
1760
+ crit.documents = [ depeche, tool ]
1761
+ end
1762
+ end
1763
+
1764
+ let(:context) do
1765
+ described_class.new(criteria)
1766
+ end
1767
+
1768
+ context "when picking a field" do
1769
+
1770
+ let(:picked) do
1771
+ context.pick(:name)
1772
+ end
1773
+
1774
+ it "returns one element" do
1775
+ expect(picked).to eq("Depeche Mode")
1776
+ end
1777
+ end
1778
+
1779
+ context "when picking multiple fields" do
1780
+
1781
+ let(:picked) do
1782
+ context.pick(:name, :likes)
1783
+ end
1784
+
1785
+ it "returns an array" do
1786
+ expect(picked).to eq([ "Depeche Mode", 3 ])
1787
+ end
1788
+ end
1789
+
1790
+ context "when no documents to pick" do
1791
+
1792
+ let(:criteria) do
1793
+ Band.all.tap do |crit|
1794
+ crit.documents = []
1795
+ end
1796
+ end
1797
+
1798
+ let(:picked) do
1799
+ context.pick(:name)
1800
+ end
1801
+
1802
+ it "returns nil" do
1803
+ expect(picked).to be_nil
1804
+ end
1805
+ end
1806
+ end
1807
+
1808
+ describe "#tally" do
1809
+ let(:fans1) { [ Fanatic.new(age:1), Fanatic.new(age:2) ] }
1810
+ let(:fans2) { [ Fanatic.new(age:1), Fanatic.new(age:2) ] }
1811
+ let(:fans3) { [ Fanatic.new(age:1), Fanatic.new(age:3) ] }
1812
+
1813
+ let(:genres1) { [ { x: 1, y: { z: 1 } }, { x: 2, y: { z: 2 } }, { y: 3 } ]}
1814
+ let(:genres2) { [ { x: 1, y: { z: 1 } }, { x: 2, y: { z: 2 } }, { y: 4 } ]}
1815
+ let(:genres3) { [ { x: 1, y: { z: 1 } }, { x: 3, y: { z: 3 } }, { y: 5 } ]}
1816
+
1817
+ let(:label1) { Label.new(name: "Atlantic") }
1818
+ let(:label2) { Label.new(name: "Atlantic") }
1819
+ let(:label3) { Label.new(name: "Columbia") }
1820
+
1821
+
1822
+ let(:band1) { Band.new(origin: "tally", name: "Depeche Mode", years: 30, sales: "1E2", label: label1, genres: genres1) }
1823
+ let(:band2) { Band.new(origin: "tally", name: "New Order", years: 30, sales: "2E3", label: label2, genres: genres2) }
1824
+ let(:band3) { Band.new(origin: "tally", name: "10,000 Maniacs", years: 30, sales: "1E2", label: label3, genres: genres3) }
1825
+ let(:band4) { Band.new(origin: "tally2", fanatics: fans1, genres: [1, 2]) }
1826
+ let(:band5) { Band.new(origin: "tally2", fanatics: fans2, genres: [1, 2]) }
1827
+ let(:band6) { Band.new(origin: "tally2", fanatics: fans3, genres: [1, 3]) }
1828
+
1829
+ let(:criteria) do
1830
+ Band.where(origin: "tally").all.tap do |crit|
1831
+ crit.documents = [ band1, band2, band3 ]
1832
+ end
1833
+ end
1834
+
1835
+ let(:criteria2) do
1836
+ Band.where(origin: "tally2").tap do |crit|
1837
+ crit.documents = [ band4, band5, band6 ]
1838
+ end
1839
+ end
1840
+
1841
+ let(:context) do
1842
+ described_class.new(criteria)
1843
+ end
1844
+
1845
+ let(:context2) do
1846
+ described_class.new(criteria2)
1847
+ end
1848
+
1849
+ context "when tallying a string" do
1850
+ let(:tally) do
1851
+ context.tally(:name)
1852
+ end
1853
+
1854
+ it "returns the correct hash" do
1855
+ expect(tally).to eq("Depeche Mode" => 1, "New Order" => 1, "10,000 Maniacs" => 1)
1856
+ end
1857
+ end
1858
+
1859
+ context "using an aliased field" do
1860
+ let(:tally) do
1861
+ context.tally(:years)
1862
+ end
1863
+
1864
+ it "returns the correct hash" do
1865
+ expect(tally).to eq(30 => 3)
1866
+ end
1867
+ end
1868
+
1869
+ context "when tallying a demongoizable field" do
1870
+ let(:tally) do
1871
+ context.tally(:sales)
1872
+ end
1873
+
1874
+ it "returns the correct hash" do
1875
+ expect(tally).to eq(BigDecimal("1E2") => 2, BigDecimal("2E3") => 1)
1876
+ end
1877
+ end
1878
+
1879
+ context "when tallying a localized field" do
1880
+ let(:d1) { Dictionary.new(description: 'en1') }
1881
+ let(:d2) { Dictionary.new(description: 'en1') }
1882
+ let(:d3) { Dictionary.new(description: 'en1') }
1883
+ let(:d4) { Dictionary.new(description: 'en2') }
1884
+
1885
+ before do
1886
+ I18n.locale = :en
1887
+ d1
1888
+ d2
1889
+ d3
1890
+ d4
1891
+ I18n.locale = :de
1892
+ d1.description = 'de1'
1893
+ d2.description = 'de1'
1894
+ d3.description = 'de2'
1895
+ d4.description = 'de3'
1896
+ I18n.locale = :en
1897
+ end
1898
+
1899
+ let(:criteria) do
1900
+ Dictionary.all.tap do |crit|
1901
+ crit.documents = [ d1, d2, d3, d4 ]
1902
+ end
1903
+ end
1904
+
1905
+ context "when getting the demongoized field" do
1906
+ let(:tallied) do
1907
+ context.tally(:description)
1908
+ end
1909
+
1910
+ it "returns the translation for the current locale" do
1911
+ expect(tallied).to eq("en1" => 3, "en2" => 1)
1912
+ end
1913
+ end
1914
+
1915
+ context "when getting a specific locale" do
1916
+ let(:tallied) do
1917
+ context.tally("description.de")
1918
+ end
1919
+
1920
+ it "returns the translation for the the specific locale" do
1921
+ expect(tallied).to eq("de1" => 2, "de2" => 1, "de3" => 1)
1922
+ end
1923
+ end
1924
+
1925
+ context "when getting the full hash" do
1926
+ let(:tallied) do
1927
+ context.tally("description_translations")
1928
+ end
1929
+
1930
+ it "returns the correct hash" do
1931
+ expect(tallied).to eq(
1932
+ {"de" => "de1", "en" => "en1" } => 2,
1933
+ {"de" => "de2", "en" => "en1" } => 1,
1934
+ {"de" => "de3", "en" => "en2" } => 1
1935
+ )
1936
+ end
1937
+ end
1938
+ end
1939
+
1940
+ context "when tallying an embedded localized field" do
1941
+
1942
+ let(:person1) { Person.create!(addresses: [ address1a, address1b ]) }
1943
+ let(:person2) { Person.create!(addresses: [ address2a, address2b ]) }
1944
+
1945
+ let(:address1a) { Address.new(name: "en1") }
1946
+ let(:address1b) { Address.new(name: "en2") }
1947
+ let(:address2a) { Address.new(name: "en1") }
1948
+ let(:address2b) { Address.new(name: "en3") }
1949
+
1950
+ before do
1951
+ I18n.locale = :en
1952
+ address1a
1953
+ address1b
1954
+ address2a
1955
+ address2b
1956
+ I18n.locale = :de
1957
+ address1a.name = "de1"
1958
+ address1b.name = "de2"
1959
+ address2a.name = "de1"
1960
+ address2b.name = "de3"
1961
+ person1
1962
+ person2
1963
+
1964
+ I18n.locale = :en
1965
+ end
1966
+
1967
+ let(:criteria) do
1968
+ Person.all.tap do |crit|
1969
+ crit.documents = [ person1, person2 ]
1970
+ end
1971
+ end
1972
+
1973
+ context "when getting the demongoized field" do
1974
+ let(:tallied) do
1975
+ context.tally("addresses.name")
1976
+ end
1977
+
1978
+ it "returns the translation for the current locale" do
1979
+ expect(tallied).to eq(
1980
+ [ "en1", "en2" ] => 1,
1981
+ [ "en1", "en3" ] => 1,
1982
+ )
1983
+ end
1984
+ end
1985
+
1986
+ context "when getting a specific locale" do
1987
+ let(:tallied) do
1988
+ context.tally("addresses.name.de")
1989
+ end
1990
+
1991
+ it "returns the translation for the the specific locale" do
1992
+ expect(tallied).to eq(
1993
+ [ "de1", "de2" ] => 1,
1994
+ [ "de1", "de3" ] => 1,
1995
+ )
1996
+ end
1997
+ end
1998
+
1999
+ context "when getting the full hash" do
2000
+ let(:tallied) do
2001
+ context.tally("addresses.name_translations")
2002
+ end
2003
+
2004
+ it "returns the correct hash" do
2005
+ expect(tallied).to eq(
2006
+ [{ "de" => "de1", "en" => "en1" }, { "de" => "de2", "en" => "en2" }] => 1,
2007
+ [{ "de" => "de1", "en" => "en1" }, { "de" => "de3", "en" => "en3" }] => 1,
2008
+ )
2009
+ end
2010
+ end
2011
+ end
2012
+
2013
+ context "when tallying an embedded field" do
2014
+ let(:tally) do
2015
+ context.tally("label.name")
2016
+ end
2017
+
2018
+ it "returns the correct hash" do
2019
+ expect(tally).to eq("Atlantic" => 2, "Columbia" => 1)
2020
+ end
2021
+ end
2022
+
2023
+ context "when tallying an element in an embeds_many field" do
2024
+
2025
+ let(:tally) do
2026
+ context2.tally("fanatics.age")
2027
+ end
2028
+
2029
+ it "returns the correct hash" do
2030
+ expect(tally).to eq(
2031
+ [1, 2] => 2,
2032
+ [1, 3] => 1
2033
+ )
2034
+ end
2035
+ end
2036
+
2037
+ context "when tallying an embeds_many field" do
2038
+
2039
+ let(:tally) do
2040
+ context2.tally("fanatics")
2041
+ end
2042
+
2043
+ it "returns the correct hash" do
2044
+ expect(tally).to eq(
2045
+ fans1 => 1,
2046
+ fans2 => 1,
2047
+ fans3 => 1,
2048
+ )
2049
+ end
2050
+ end
2051
+
2052
+ context "when tallying a field of type array" do
2053
+
2054
+ let(:tally) do
2055
+ context2.tally("genres")
2056
+ end
2057
+
2058
+ it "returns the correct hash" do
2059
+ expect(tally).to eq(
2060
+ [1, 2] => 2,
2061
+ [1, 3] => 1
2062
+ )
2063
+ end
2064
+ end
2065
+
2066
+ context "when tallying an element from an array of hashes" do
2067
+
2068
+ let(:tally) do
2069
+ context.tally("genres.x")
2070
+ end
2071
+
2072
+ it "returns the correct hash without the nil keys" do
2073
+ expect(tally).to eq(
2074
+ [1, 2] => 2,
2075
+ [1, 3] => 1
2076
+ )
2077
+ end
2078
+ end
2079
+
2080
+ context "when tallying an element from an array of hashes; with duplicate" do
2081
+
2082
+ let(:band4) { Band.new(origin: "tally", genres: [ { x: 1 }, {x: 1} ] ) }
2083
+
2084
+ let(:criteria) do
2085
+ Band.where(origin: "tally").all.tap do |crit|
2086
+ crit.documents = [ band1, band2, band3, band4 ]
2087
+ end
2088
+ end
2089
+
2090
+ let(:tally) do
2091
+ context.tally("genres.x")
2092
+ end
2093
+
2094
+ it "returns the correct hash without the nil keys" do
2095
+ expect(tally).to eq(
2096
+ [1, 2] => 2,
2097
+ [1, 3] => 1,
2098
+ [1, 1] => 1,
2099
+ )
2100
+ end
2101
+ end
2102
+
2103
+ context "when tallying an aliased field of type array" do
2104
+
2105
+ let(:person1) { Person.new(array: [ 1, 2 ]) }
2106
+ let(:person2) { Person.new(array: [ 1, 3 ]) }
2107
+
2108
+ let(:criteria) do
2109
+ Person.all.tap do |crit|
2110
+ crit.documents = [ person1, person2 ]
2111
+ end
2112
+ end
2113
+
2114
+ let(:tally) do
2115
+ context.tally("array")
2116
+ end
2117
+
2118
+ it "returns the correct hash" do
2119
+ expect(tally).to eq(
2120
+ [1, 2] => 1,
2121
+ [1, 3] => 1
2122
+ )
2123
+ end
2124
+ end
2125
+
2126
+ context "when going multiple levels deep in arrays" do
2127
+
2128
+ let(:tally) do
2129
+ context.tally("genres.y.z")
2130
+ end
2131
+
2132
+ it "returns the correct hash" do
2133
+ expect(tally).to eq(
2134
+ [1, 2] => 2,
2135
+ [1, 3] => 1
2136
+ )
2137
+ end
2138
+ end
2139
+
2140
+ context "when going multiple levels deep in an array" do
2141
+
2142
+ let(:tally) do
2143
+ context.tally("genres.y.z")
2144
+ end
2145
+
2146
+ it "returns the correct hash" do
2147
+ expect(tally).to eq(
2148
+ [1, 2] => 2,
2149
+ [1, 3] => 1
2150
+ )
2151
+ end
2152
+ end
2153
+
2154
+ context "when tallying deeply nested arrays/embedded associations" do
2155
+
2156
+ let(:person1) { Person.new(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))) ]) }
2157
+ let(:person2) { Person.new(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))) ]) }
2158
+ let(:person3) { Person.new(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 3 } } ]))) ]) }
2159
+
2160
+ let(:criteria) do
2161
+ Person.all.tap do |crit|
2162
+ crit.documents = [ person1, person2, person3 ]
2163
+ end
2164
+ end
2165
+
2166
+ let(:tally) do
2167
+ context.tally("addresses.code.deepest.array.y.z")
2168
+ end
2169
+
2170
+ it "returns the correct hash" do
2171
+ expect(tally).to eq(
2172
+ [ [ 1, 2 ] ] => 2,
2173
+ [ [ 1, 3 ] ] => 1
2174
+ )
2175
+ end
2176
+ end
2177
+
2178
+ context "when tallying deeply nested arrays/embedded associations" do
2179
+
2180
+ let(:person1) do
2181
+ Person.new(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))),
2182
+ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))) ])
2183
+ end
2184
+
2185
+ let(:person2) do
2186
+ Person.new(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))),
2187
+ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))) ])
2188
+ end
2189
+
2190
+ let(:person3) do
2191
+ Person.new(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 3 } } ]))),
2192
+ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 3 } } ]))) ])
2193
+ end
2194
+
2195
+ let(:criteria) do
2196
+ Person.all.tap do |crit|
2197
+ crit.documents = [ person1, person2, person3 ]
2198
+ end
2199
+ end
2200
+
2201
+ let(:tally) do
2202
+ context.tally("addresses.code.deepest.array.y.z")
2203
+ end
2204
+
2205
+ it "returns the correct hash" do
2206
+ expect(tally).to eq(
2207
+ [ [ 1, 2 ], [ 1, 2 ] ] => 2,
2208
+ [ [ 1, 3 ], [ 1, 3 ] ] => 1
2209
+ )
2210
+ end
2211
+ end
2212
+
2213
+ context "when some keys are missing" do
2214
+
2215
+ let(:criteria) do
2216
+ Band.where(origin: "tally").all.tap do |crit|
2217
+ crit.documents = [ band1, band2, band3 ]
2218
+ 3.times{ crit.documents << Band.new(origin: "tally") }
2219
+ end
2220
+ end
2221
+
2222
+ let(:tally) do
2223
+ context.tally(:name)
2224
+ end
2225
+
2226
+ it "returns the correct hash" do
2227
+ expect(tally).to eq(
2228
+ "Depeche Mode" => 1,
2229
+ "New Order" => 1,
2230
+ "10,000 Maniacs" => 1,
2231
+ nil => 3
2232
+ )
2233
+ end
2234
+ end
2235
+
2236
+ context "when the first element is an embeds_one" do
2237
+ let(:person1) { Person.create!(name: Name.new(translations: [ Translation.new(language: 1), Translation.new(language: 2) ])) }
2238
+ let(:person2) { Person.create!(name: Name.new(translations: [ Translation.new(language: 1), Translation.new(language: 2) ])) }
2239
+ let(:person3) { Person.create!(name: Name.new(translations: [ Translation.new(language: 1), Translation.new(language: 3) ])) }
2240
+
2241
+ let(:criteria) do
2242
+ Person.all.tap do |crit|
2243
+ crit.documents = [ person1, person2, person3 ]
2244
+ end
2245
+ end
2246
+
2247
+ let(:tally) do
2248
+ context.tally("name.translations.language")
2249
+ end
2250
+
2251
+ it "returns the correct hash" do
2252
+ expect(tally).to eq(
2253
+ [1, 2] => 2,
2254
+ [1, 3] => 1
2255
+ )
2256
+ end
2257
+ end
2258
+ end
2259
+
1753
2260
  describe '#inc' do
1754
2261
 
1755
2262
  let(:criteria) do