mongoid 5.4.0 → 6.4.8

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 (301) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +3 -3
  4. data/Rakefile +26 -0
  5. data/lib/config/locales/en.yml +40 -0
  6. data/lib/mongoid/atomic/modifiers.rb +2 -2
  7. data/lib/mongoid/atomic.rb +5 -5
  8. data/lib/mongoid/attributes/readonly.rb +22 -0
  9. data/lib/mongoid/attributes.rb +22 -21
  10. data/lib/mongoid/cacheable.rb +36 -0
  11. data/lib/mongoid/changeable.rb +36 -0
  12. data/lib/mongoid/clients/options.rb +55 -250
  13. data/lib/mongoid/clients/sessions.rb +113 -0
  14. data/lib/mongoid/clients/storage_options.rb +2 -69
  15. data/lib/mongoid/clients.rb +10 -63
  16. data/lib/mongoid/composable.rb +29 -2
  17. data/lib/mongoid/config.rb +1 -0
  18. data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
  19. data/lib/mongoid/contextual/atomic.rb +4 -4
  20. data/lib/mongoid/contextual/map_reduce.rb +7 -3
  21. data/lib/mongoid/contextual/memory.rb +9 -4
  22. data/lib/mongoid/contextual/mongo.rb +65 -30
  23. data/lib/mongoid/contextual/none.rb +12 -0
  24. data/lib/mongoid/copyable.rb +13 -6
  25. data/lib/mongoid/criteria/marshalable.rb +2 -2
  26. data/lib/mongoid/criteria/modifiable.rb +29 -3
  27. data/lib/mongoid/criteria/options.rb +25 -0
  28. data/lib/mongoid/criteria/queryable/aggregable.rb +120 -0
  29. data/lib/mongoid/criteria/queryable/extensions/array.rb +185 -0
  30. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +37 -0
  31. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +34 -0
  32. data/lib/mongoid/criteria/queryable/extensions/date.rb +63 -0
  33. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +53 -0
  34. data/lib/mongoid/criteria/queryable/extensions/hash.rb +200 -0
  35. data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +86 -0
  36. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +90 -0
  37. data/lib/mongoid/criteria/queryable/extensions/object.rb +206 -0
  38. data/lib/mongoid/criteria/queryable/extensions/range.rb +70 -0
  39. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +79 -0
  40. data/lib/mongoid/criteria/queryable/extensions/set.rb +34 -0
  41. data/lib/mongoid/criteria/queryable/extensions/string.rb +137 -0
  42. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +79 -0
  43. data/lib/mongoid/criteria/queryable/extensions/time.rb +60 -0
  44. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +54 -0
  45. data/lib/mongoid/criteria/queryable/extensions.rb +28 -0
  46. data/lib/mongoid/criteria/queryable/forwardable.rb +65 -0
  47. data/lib/mongoid/criteria/queryable/key.rb +103 -0
  48. data/lib/mongoid/criteria/queryable/macroable.rb +27 -0
  49. data/lib/mongoid/criteria/queryable/mergeable.rb +273 -0
  50. data/lib/mongoid/criteria/queryable/optional.rb +429 -0
  51. data/lib/mongoid/criteria/queryable/options.rb +153 -0
  52. data/lib/mongoid/criteria/queryable/pipeline.rb +111 -0
  53. data/lib/mongoid/criteria/queryable/selectable.rb +689 -0
  54. data/lib/mongoid/criteria/queryable/selector.rb +212 -0
  55. data/lib/mongoid/criteria/queryable/smash.rb +104 -0
  56. data/lib/mongoid/criteria/queryable.rb +87 -0
  57. data/lib/mongoid/criteria.rb +6 -2
  58. data/lib/mongoid/document.rb +34 -41
  59. data/lib/mongoid/errors/ambiguous_relationship.rb +1 -1
  60. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +1 -1
  61. data/lib/mongoid/errors/invalid_field.rb +2 -2
  62. data/lib/mongoid/errors/invalid_persistence_option.rb +29 -0
  63. data/lib/mongoid/errors/invalid_relation.rb +66 -0
  64. data/lib/mongoid/errors/invalid_session_use.rb +24 -0
  65. data/lib/mongoid/errors.rb +3 -0
  66. data/lib/mongoid/evolvable.rb +1 -1
  67. data/lib/mongoid/extensions/big_decimal.rb +17 -8
  68. data/lib/mongoid/extensions/date.rb +4 -1
  69. data/lib/mongoid/extensions/decimal128.rb +3 -3
  70. data/lib/mongoid/extensions/hash.rb +1 -0
  71. data/lib/mongoid/extensions/regexp.rb +1 -0
  72. data/lib/mongoid/extensions/string.rb +6 -3
  73. data/lib/mongoid/extensions/time.rb +4 -1
  74. data/lib/mongoid/extensions.rb +0 -4
  75. data/lib/mongoid/factory.rb +2 -1
  76. data/lib/mongoid/fields/validators/macro.rb +18 -0
  77. data/lib/mongoid/findable.rb +2 -2
  78. data/lib/mongoid/indexable.rb +16 -14
  79. data/lib/mongoid/interceptable.rb +9 -22
  80. data/lib/mongoid/matchable/all.rb +2 -2
  81. data/lib/mongoid/matchable/and.rb +3 -3
  82. data/lib/mongoid/matchable/default.rb +2 -2
  83. data/lib/mongoid/matchable/elem_match.rb +28 -0
  84. data/lib/mongoid/matchable/exists.rb +2 -2
  85. data/lib/mongoid/matchable/gt.rb +4 -2
  86. data/lib/mongoid/matchable/gte.rb +4 -2
  87. data/lib/mongoid/matchable/in.rb +2 -2
  88. data/lib/mongoid/matchable/lt.rb +4 -2
  89. data/lib/mongoid/matchable/lte.rb +4 -2
  90. data/lib/mongoid/matchable/ne.rb +2 -2
  91. data/lib/mongoid/matchable/nin.rb +2 -2
  92. data/lib/mongoid/matchable/nor.rb +37 -0
  93. data/lib/mongoid/matchable/or.rb +3 -3
  94. data/lib/mongoid/matchable/regexp.rb +3 -3
  95. data/lib/mongoid/matchable/size.rb +2 -2
  96. data/lib/mongoid/matchable.rb +16 -7
  97. data/lib/mongoid/persistable/creatable.rb +5 -3
  98. data/lib/mongoid/persistable/deletable.rb +5 -3
  99. data/lib/mongoid/persistable/destroyable.rb +1 -5
  100. data/lib/mongoid/persistable/settable.rb +5 -5
  101. data/lib/mongoid/persistable/updatable.rb +7 -14
  102. data/lib/mongoid/persistable/upsertable.rb +2 -1
  103. data/lib/mongoid/persistable.rb +4 -6
  104. data/lib/mongoid/persistence_context.rb +220 -0
  105. data/lib/mongoid/query_cache.rb +67 -23
  106. data/lib/mongoid/railtie.rb +17 -1
  107. data/lib/mongoid/railties/controller_runtime.rb +86 -0
  108. data/lib/mongoid/relations/accessors.rb +3 -0
  109. data/lib/mongoid/relations/auto_save.rb +12 -4
  110. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +4 -4
  111. data/lib/mongoid/relations/counter_cache.rb +15 -5
  112. data/lib/mongoid/relations/eager/base.rb +3 -3
  113. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +2 -2
  114. data/lib/mongoid/relations/eager/has_many.rb +1 -1
  115. data/lib/mongoid/relations/eager.rb +6 -11
  116. data/lib/mongoid/relations/embedded/batchable.rb +20 -18
  117. data/lib/mongoid/relations/embedded/in.rb +13 -1
  118. data/lib/mongoid/relations/embedded/many.rb +51 -10
  119. data/lib/mongoid/relations/embedded/one.rb +14 -1
  120. data/lib/mongoid/relations/macros.rb +9 -1
  121. data/lib/mongoid/relations/many.rb +4 -0
  122. data/lib/mongoid/relations/metadata.rb +3 -3
  123. data/lib/mongoid/relations/options.rb +2 -2
  124. data/lib/mongoid/relations/proxy.rb +1 -31
  125. data/lib/mongoid/relations/referenced/in.rb +19 -10
  126. data/lib/mongoid/relations/referenced/many.rb +30 -26
  127. data/lib/mongoid/relations/referenced/many_to_many.rb +20 -13
  128. data/lib/mongoid/relations/referenced/one.rb +15 -1
  129. data/lib/mongoid/relations/synchronization.rb +12 -12
  130. data/lib/mongoid/relations/targets/enumerable.rb +24 -4
  131. data/lib/mongoid/relations/touchable.rb +7 -4
  132. data/lib/mongoid/reloadable.rb +2 -2
  133. data/lib/mongoid/scopable.rb +3 -3
  134. data/lib/mongoid/serializable.rb +1 -1
  135. data/lib/mongoid/stateful.rb +1 -0
  136. data/lib/mongoid/tasks/database.rb +3 -2
  137. data/lib/mongoid/threaded.rb +74 -0
  138. data/lib/mongoid/traversable.rb +1 -1
  139. data/lib/mongoid/validatable/uniqueness.rb +1 -2
  140. data/lib/mongoid/version.rb +1 -1
  141. data/lib/mongoid.rb +6 -6
  142. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +18 -3
  143. data/spec/app/models/agent.rb +2 -0
  144. data/spec/app/models/album.rb +5 -1
  145. data/spec/app/models/array_field.rb +7 -0
  146. data/spec/app/models/artist.rb +21 -0
  147. data/spec/app/models/band.rb +3 -0
  148. data/spec/app/models/book.rb +2 -1
  149. data/spec/app/models/delegating_patient.rb +16 -0
  150. data/spec/app/models/dokument.rb +1 -0
  151. data/spec/app/models/ordered_post.rb +5 -0
  152. data/spec/app/models/oscar.rb +1 -2
  153. data/spec/app/models/page.rb +1 -1
  154. data/spec/app/models/person.rb +3 -3
  155. data/spec/app/models/princess.rb +2 -0
  156. data/spec/app/models/record.rb +1 -0
  157. data/spec/app/models/subscription.rb +1 -0
  158. data/spec/app/models/thing.rb +1 -1
  159. data/spec/config/mongoid.yml +15 -0
  160. data/spec/integration/document_spec.rb +22 -0
  161. data/spec/mongoid/atomic/modifiers_spec.rb +3 -3
  162. data/spec/mongoid/atomic_spec.rb +5 -5
  163. data/spec/mongoid/attributes/nested_spec.rb +18 -14
  164. data/spec/mongoid/attributes/readonly_spec.rb +87 -44
  165. data/spec/mongoid/attributes_spec.rb +90 -5
  166. data/spec/mongoid/cacheable_spec.rb +112 -0
  167. data/spec/mongoid/changeable_spec.rb +58 -0
  168. data/spec/mongoid/clients/factory_spec.rb +80 -28
  169. data/spec/mongoid/clients/options_spec.rb +396 -95
  170. data/spec/mongoid/clients/sessions_spec.rb +334 -0
  171. data/spec/mongoid/clients_spec.rb +243 -101
  172. data/spec/mongoid/composable_spec.rb +7 -0
  173. data/spec/mongoid/config_spec.rb +67 -11
  174. data/spec/mongoid/contextual/atomic_spec.rb +3 -3
  175. data/spec/mongoid/contextual/geo_near_spec.rb +1 -0
  176. data/spec/mongoid/contextual/mongo_spec.rb +275 -22
  177. data/spec/mongoid/contextual/none_spec.rb +15 -0
  178. data/spec/mongoid/copyable_spec.rb +13 -4
  179. data/spec/mongoid/criteria/modifiable_spec.rb +297 -16
  180. data/spec/mongoid/criteria/options_spec.rb +29 -0
  181. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +370 -0
  182. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +523 -0
  183. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +59 -0
  184. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +58 -0
  185. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +213 -0
  186. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +330 -0
  187. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +405 -0
  188. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +58 -0
  189. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +65 -0
  190. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +327 -0
  191. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +65 -0
  192. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +77 -0
  193. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +108 -0
  194. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +309 -0
  195. data/spec/mongoid/{extensions/origin → criteria/queryable/extensions}/regexp_raw_spec.rb +2 -2
  196. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +90 -0
  197. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +39 -0
  198. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +302 -0
  199. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +167 -0
  200. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +376 -0
  201. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +347 -0
  202. data/spec/mongoid/criteria/queryable/forwardable_spec.rb +87 -0
  203. data/spec/mongoid/criteria/queryable/key_spec.rb +52 -0
  204. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +49 -0
  205. data/spec/mongoid/criteria/queryable/optional_spec.rb +1799 -0
  206. data/spec/mongoid/criteria/queryable/options_spec.rb +360 -0
  207. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +200 -0
  208. data/spec/mongoid/criteria/queryable/queryable_spec.rb +137 -0
  209. data/spec/mongoid/criteria/queryable/selectable_spec.rb +4242 -0
  210. data/spec/mongoid/criteria/queryable/selector_spec.rb +844 -0
  211. data/spec/mongoid/criteria/queryable/smash_spec.rb +30 -0
  212. data/spec/mongoid/criteria/scopable_spec.rb +81 -0
  213. data/spec/mongoid/criteria_spec.rb +156 -22
  214. data/spec/mongoid/document_spec.rb +100 -90
  215. data/spec/mongoid/errors/invalid_relation_spec.rb +37 -0
  216. data/spec/mongoid/errors/mongoid_error_spec.rb +6 -3
  217. data/spec/mongoid/extensions/big_decimal_spec.rb +321 -19
  218. data/spec/mongoid/extensions/boolean_spec.rb +14 -0
  219. data/spec/mongoid/extensions/date_spec.rb +2 -6
  220. data/spec/mongoid/extensions/date_time_spec.rb +2 -6
  221. data/spec/mongoid/extensions/decimal128_spec.rb +1 -1
  222. data/spec/mongoid/extensions/float_spec.rb +8 -1
  223. data/spec/mongoid/extensions/hash_spec.rb +15 -0
  224. data/spec/mongoid/extensions/integer_spec.rb +8 -1
  225. data/spec/mongoid/extensions/object_spec.rb +11 -0
  226. data/spec/mongoid/extensions/regexp_spec.rb +23 -0
  227. data/spec/mongoid/extensions/string_spec.rb +53 -4
  228. data/spec/mongoid/extensions/time_spec.rb +2 -6
  229. data/spec/mongoid/extensions/time_with_zone_spec.rb +2 -6
  230. data/spec/mongoid/factory_spec.rb +11 -0
  231. data/spec/mongoid/fields_spec.rb +1 -1
  232. data/spec/mongoid/findable_spec.rb +47 -2
  233. data/spec/mongoid/indexable_spec.rb +15 -3
  234. data/spec/mongoid/interceptable_spec.rb +85 -19
  235. data/spec/mongoid/matchable/all_spec.rb +4 -4
  236. data/spec/mongoid/matchable/and_spec.rb +10 -10
  237. data/spec/mongoid/matchable/default_spec.rb +12 -12
  238. data/spec/mongoid/matchable/elem_match_spec.rb +86 -0
  239. data/spec/mongoid/matchable/exists_spec.rb +5 -5
  240. data/spec/mongoid/matchable/gt_spec.rb +18 -7
  241. data/spec/mongoid/matchable/gte_spec.rb +17 -7
  242. data/spec/mongoid/matchable/in_spec.rb +5 -5
  243. data/spec/mongoid/matchable/lt_spec.rb +18 -7
  244. data/spec/mongoid/matchable/lte_spec.rb +18 -7
  245. data/spec/mongoid/matchable/ne_spec.rb +5 -5
  246. data/spec/mongoid/matchable/nin_spec.rb +5 -5
  247. data/spec/mongoid/matchable/nor_spec.rb +209 -0
  248. data/spec/mongoid/matchable/or_spec.rb +7 -7
  249. data/spec/mongoid/matchable/regexp_spec.rb +5 -5
  250. data/spec/mongoid/matchable/size_spec.rb +3 -3
  251. data/spec/mongoid/matchable_spec.rb +199 -54
  252. data/spec/mongoid/persistable/creatable_spec.rb +7 -2
  253. data/spec/mongoid/persistable/deletable_spec.rb +35 -1
  254. data/spec/mongoid/persistable/destroyable_spec.rb +25 -2
  255. data/spec/mongoid/persistable/incrementable_spec.rb +6 -6
  256. data/spec/mongoid/persistable/savable_spec.rb +34 -29
  257. data/spec/mongoid/persistable/settable_spec.rb +77 -27
  258. data/spec/mongoid/persistable/updatable_spec.rb +182 -3
  259. data/spec/mongoid/persistable_spec.rb +16 -16
  260. data/spec/mongoid/persistence_context_spec.rb +694 -0
  261. data/spec/mongoid/positional_spec.rb +1 -1
  262. data/spec/mongoid/query_cache_spec.rb +170 -12
  263. data/spec/mongoid/relations/accessors_spec.rb +1 -1
  264. data/spec/mongoid/relations/auto_save_spec.rb +39 -6
  265. data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +4 -4
  266. data/spec/mongoid/relations/builders_spec.rb +37 -10
  267. data/spec/mongoid/relations/counter_cache_spec.rb +64 -3
  268. data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +16 -0
  269. data/spec/mongoid/relations/eager_spec.rb +40 -0
  270. data/spec/mongoid/relations/embedded/many_spec.rb +305 -59
  271. data/spec/mongoid/relations/embedded/one_spec.rb +2 -1
  272. data/spec/mongoid/relations/macros_spec.rb +415 -7
  273. data/spec/mongoid/relations/metadata_spec.rb +15 -1
  274. data/spec/mongoid/relations/proxy_spec.rb +27 -1
  275. data/spec/mongoid/relations/referenced/in_spec.rb +41 -1
  276. data/spec/mongoid/relations/referenced/many_spec.rb +35 -25
  277. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +14 -26
  278. data/spec/mongoid/relations/synchronization_spec.rb +48 -2
  279. data/spec/mongoid/relations/targets/enumerable_spec.rb +108 -0
  280. data/spec/mongoid/relations/touchable_spec.rb +40 -0
  281. data/spec/mongoid/reloadable_spec.rb +51 -0
  282. data/spec/mongoid/scopable_spec.rb +13 -0
  283. data/spec/mongoid/serializable_spec.rb +0 -50
  284. data/spec/mongoid/threaded_spec.rb +68 -0
  285. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  286. data/spec/mongoid/validatable/uniqueness_spec.rb +18 -9
  287. data/spec/mongoid/validatable_spec.rb +16 -0
  288. data/spec/rails/controller_extension/controller_runtime_spec.rb +110 -0
  289. data/spec/spec_helper.rb +101 -8
  290. data/spec/support/cluster_config.rb +158 -0
  291. data/spec/support/constraints.rb +101 -0
  292. data/spec/support/macros.rb +20 -0
  293. data/spec/support/session_registry.rb +50 -0
  294. data/spec/support/spec_config.rb +42 -0
  295. data.tar.gz.sig +0 -0
  296. metadata +163 -61
  297. metadata.gz.sig +0 -0
  298. data/lib/mongoid/clients/thread_options.rb +0 -19
  299. data/lib/mongoid/extensions/origin/regexp_raw.rb +0 -43
  300. data/lib/mongoid/railties/document.rb +0 -12
  301. data/spec/mongoid/railties/document_spec.rb +0 -24
@@ -0,0 +1,370 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Criteria::Queryable::Aggregable do
4
+
5
+ let(:query) do
6
+ Mongoid::Query.new("id" => "_id", "alias" => "a")
7
+ end
8
+
9
+ shared_examples_for "an aggregable object" do
10
+
11
+ it "clones the queryable" do
12
+ expect(aggregation).to_not equal(query)
13
+ end
14
+
15
+ it "sets the aggrating flag" do
16
+ expect(aggregation).to be_aggregating
17
+ end
18
+ end
19
+
20
+ describe "#project" do
21
+
22
+ context "when no selection or options exist" do
23
+
24
+ let(:aggregation) do
25
+ query.project(author: 1, title: 0)
26
+ end
27
+
28
+ let!(:pipeline) do
29
+ aggregation.pipeline
30
+ end
31
+
32
+ it "sets the projection" do
33
+ expect(pipeline).to eq([
34
+ { "$project" => { "author" => 1, "title" => 0 }}
35
+ ])
36
+ end
37
+
38
+ it_behaves_like "an aggregable object"
39
+ end
40
+
41
+ context "when the field is aliased" do
42
+
43
+ let(:aggregation) do
44
+ query.project(id: 1, title: "$docTitle")
45
+ end
46
+
47
+ let!(:pipeline) do
48
+ aggregation.pipeline
49
+ end
50
+
51
+ it "sets the aliased projection" do
52
+ expect(pipeline).to eq([
53
+ { "$project" => { "_id" => 1, "title" => "$docTitle" }}
54
+ ])
55
+ end
56
+
57
+ it_behaves_like "an aggregable object"
58
+ end
59
+
60
+ context "when selection exists" do
61
+
62
+ let(:aggregation) do
63
+ query.where(name: "test").project(author: 1, title: 0)
64
+ end
65
+
66
+ let!(:pipeline) do
67
+ aggregation.pipeline
68
+ end
69
+
70
+ it "converts the selection to a $match" do
71
+ expect(pipeline).to eq([
72
+ { "$match" => { "name" => "test" }},
73
+ { "$project" => { "author" => 1, "title" => 0 }}
74
+ ])
75
+ end
76
+
77
+ it_behaves_like "an aggregable object"
78
+ end
79
+
80
+ context "when options exist" do
81
+
82
+ context "when the option is a sort" do
83
+
84
+ let(:aggregation) do
85
+ query.asc(:name).project(author: 1, title: 0)
86
+ end
87
+
88
+ let!(:pipeline) do
89
+ aggregation.pipeline
90
+ end
91
+
92
+ it "converts the option to a $sort" do
93
+ expect(pipeline).to eq([
94
+ { "$sort" => { "name" => 1 }},
95
+ { "$project" => { "author" => 1, "title" => 0 }}
96
+ ])
97
+ end
98
+
99
+ it_behaves_like "an aggregable object"
100
+ end
101
+
102
+ context "when the option is a limit" do
103
+
104
+ let(:aggregation) do
105
+ query.limit(10).project(author: 1, title: 0)
106
+ end
107
+
108
+ let!(:pipeline) do
109
+ aggregation.pipeline
110
+ end
111
+
112
+ it "converts the option to a $sort" do
113
+ expect(pipeline).to eq([
114
+ { "$limit" => 10 },
115
+ { "$project" => { "author" => 1, "title" => 0 }}
116
+ ])
117
+ end
118
+
119
+ it_behaves_like "an aggregable object"
120
+ end
121
+
122
+ context "when the option is a skip" do
123
+
124
+ let(:aggregation) do
125
+ query.skip(10).project(author: 1, title: 0)
126
+ end
127
+
128
+ let!(:pipeline) do
129
+ aggregation.pipeline
130
+ end
131
+
132
+ it "converts the option to a $sort" do
133
+ expect(pipeline).to eq([
134
+ { "$skip" => 10 },
135
+ { "$project" => { "author" => 1, "title" => 0 }}
136
+ ])
137
+ end
138
+
139
+ it_behaves_like "an aggregable object"
140
+ end
141
+ end
142
+
143
+ context "when selection and options exist" do
144
+
145
+ let(:aggregation) do
146
+ query.skip(10).where(name: "test").project(author: 1, title: 0)
147
+ end
148
+
149
+ let!(:pipeline) do
150
+ aggregation.pipeline
151
+ end
152
+
153
+ it "converts the option to a $sort" do
154
+ expect(pipeline).to eq([
155
+ { "$match" => { "name" => "test" }},
156
+ { "$skip" => 10 },
157
+ { "$project" => { "author" => 1, "title" => 0 }}
158
+ ])
159
+ end
160
+
161
+ it_behaves_like "an aggregable object"
162
+ end
163
+ end
164
+
165
+ describe "#unwind" do
166
+
167
+ context "when another pipeline operation exists" do
168
+
169
+ let(:aggregation) do
170
+ query.project(name: 1).unwind(:author)
171
+ end
172
+
173
+ let!(:pipeline) do
174
+ aggregation.pipeline
175
+ end
176
+
177
+ it "adds the unwind to the pipeline" do
178
+ expect(pipeline).to eq([
179
+ { "$project" => { "name" => 1 }},
180
+ { "$unwind" => "$author" }
181
+ ])
182
+ end
183
+
184
+ it_behaves_like "an aggregable object"
185
+ end
186
+
187
+ context "when provided a symbol" do
188
+
189
+ context "when the symbol begins with $" do
190
+
191
+ let(:aggregation) do
192
+ query.unwind(:$author)
193
+ end
194
+
195
+ let!(:pipeline) do
196
+ aggregation.pipeline
197
+ end
198
+
199
+ it "converts the symbol to a string" do
200
+ expect(pipeline).to eq([{ "$unwind" => "$author" }])
201
+ end
202
+
203
+ it_behaves_like "an aggregable object"
204
+ end
205
+
206
+ context "when the symbol does not begin with $" do
207
+
208
+ let(:aggregation) do
209
+ query.unwind(:author)
210
+ end
211
+
212
+ let!(:pipeline) do
213
+ aggregation.pipeline
214
+ end
215
+
216
+ it "converts the symbol to a string and prepends $" do
217
+ expect(pipeline).to eq([{ "$unwind" => "$author" }])
218
+ end
219
+
220
+ it_behaves_like "an aggregable object"
221
+ end
222
+ end
223
+
224
+ context "when provided a string" do
225
+
226
+ context "when the string begins with $" do
227
+
228
+ let(:aggregation) do
229
+ query.unwind("$author")
230
+ end
231
+
232
+ let!(:pipeline) do
233
+ aggregation.pipeline
234
+ end
235
+
236
+ it "sets the string" do
237
+ expect(pipeline).to eq([{ "$unwind" => "$author" }])
238
+ end
239
+
240
+ it_behaves_like "an aggregable object"
241
+ end
242
+
243
+ context "when the string does not begin with $" do
244
+
245
+ let(:aggregation) do
246
+ query.unwind(:author)
247
+ end
248
+
249
+ let!(:pipeline) do
250
+ aggregation.pipeline
251
+ end
252
+
253
+ it "prepends $ to the string" do
254
+ expect(pipeline).to eq([{ "$unwind" => "$author" }])
255
+ end
256
+
257
+ it_behaves_like "an aggregable object"
258
+ end
259
+ end
260
+
261
+ context "when provided a string alias" do
262
+
263
+ context "when the string does not begin with $" do
264
+
265
+ let(:aggregation) do
266
+ query.unwind(:alias)
267
+ end
268
+
269
+ let!(:pipeline) do
270
+ aggregation.pipeline
271
+ end
272
+
273
+ it "prepends $ to the string" do
274
+ expect(pipeline).to eq([{ "$unwind" => "$a" }])
275
+ end
276
+
277
+ it_behaves_like "an aggregable object"
278
+ end
279
+ end
280
+ end
281
+
282
+ describe "#group" do
283
+
284
+ context "when the expression fields are not aliased" do
285
+
286
+ context "when using full notation" do
287
+
288
+ let(:aggregation) do
289
+ query.group(count: { "$sum" => 1 }, max: { "$max" => "likes" })
290
+ end
291
+
292
+ let!(:pipeline) do
293
+ aggregation.pipeline
294
+ end
295
+
296
+ it "adds the group operation to the pipeline" do
297
+ expect(pipeline).to eq([
298
+ { "$group" => { "count" => { "$sum" => 1 }, "max" => { "$max" => "likes" }}}
299
+ ])
300
+ end
301
+
302
+ it_behaves_like "an aggregable object"
303
+ end
304
+
305
+ context "when using symbol shortcuts" do
306
+
307
+ let(:aggregation) do
308
+ query.group(:count.sum => 1, :max.max => "likes")
309
+ end
310
+
311
+ let!(:pipeline) do
312
+ aggregation.pipeline
313
+ end
314
+
315
+ it "adds the group operation to the pipeline" do
316
+ expect(pipeline).to eq([
317
+ { "$group" => { "count" => { "$sum" => 1 }, "max" => { "$max" => "likes" }}}
318
+ ])
319
+ end
320
+
321
+ it_behaves_like "an aggregable object"
322
+ end
323
+ end
324
+
325
+ context "when the expression fields are aliased" do
326
+
327
+ context "when using full notation" do
328
+
329
+ let(:aggregation) do
330
+ query.group(count: { "$sum" => 1 }, max: { "$max" => "alias" })
331
+ end
332
+
333
+ let!(:pipeline) do
334
+ aggregation.pipeline
335
+ end
336
+
337
+ it "adds the group operation to the pipeline" do
338
+ pending
339
+ fail
340
+ expect(pipeline).to eq([
341
+ { "$group" => { "count" => { "$sum" => 1 }, "max" => { "$max" => "a" }}}
342
+ ])
343
+ end
344
+
345
+ it_behaves_like "an aggregable object"
346
+ end
347
+
348
+ context "when using symbol shortcuts" do
349
+
350
+ let(:aggregation) do
351
+ query.group(:count.sum => 1, :max.max => "alias")
352
+ end
353
+
354
+ let!(:pipeline) do
355
+ aggregation.pipeline
356
+ end
357
+
358
+ it "adds the group operation to the pipeline" do
359
+ pending
360
+ fail
361
+ expect(pipeline).to eq([
362
+ { "$group" => { "count" => { "$sum" => 1 }, "max" => { "$max" => "a" }}}
363
+ ])
364
+ end
365
+
366
+ it_behaves_like "an aggregable object"
367
+ end
368
+ end
369
+ end
370
+ end