mongoid 5.4.1 → 6.1.1

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 (260) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +3 -3
  3. data/lib/config/locales/en.yml +19 -0
  4. data/lib/mongoid.rb +4 -4
  5. data/lib/mongoid/atomic.rb +2 -2
  6. data/lib/mongoid/atomic/modifiers.rb +8 -12
  7. data/lib/mongoid/attributes.rb +22 -21
  8. data/lib/mongoid/attributes/readonly.rb +22 -0
  9. data/lib/mongoid/cacheable.rb +36 -0
  10. data/lib/mongoid/changeable.rb +36 -0
  11. data/lib/mongoid/clients.rb +8 -63
  12. data/lib/mongoid/clients/options.rb +55 -250
  13. data/lib/mongoid/clients/storage_options.rb +1 -69
  14. data/lib/mongoid/composable.rb +29 -3
  15. data/lib/mongoid/config.rb +1 -0
  16. data/lib/mongoid/contextual/atomic.rb +5 -8
  17. data/lib/mongoid/contextual/map_reduce.rb +0 -4
  18. data/lib/mongoid/contextual/memory.rb +2 -2
  19. data/lib/mongoid/contextual/mongo.rb +40 -22
  20. data/lib/mongoid/contextual/none.rb +12 -0
  21. data/lib/mongoid/copyable.rb +13 -6
  22. data/lib/mongoid/criteria.rb +5 -2
  23. data/lib/mongoid/criteria/marshalable.rb +2 -2
  24. data/lib/mongoid/criteria/modifiable.rb +17 -1
  25. data/lib/mongoid/criteria/options.rb +25 -0
  26. data/lib/mongoid/criteria/queryable.rb +87 -0
  27. data/lib/mongoid/criteria/queryable/aggregable.rb +120 -0
  28. data/lib/mongoid/criteria/queryable/extensions.rb +28 -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/forwardable.rb +65 -0
  46. data/lib/mongoid/criteria/queryable/key.rb +103 -0
  47. data/lib/mongoid/criteria/queryable/macroable.rb +27 -0
  48. data/lib/mongoid/criteria/queryable/mergeable.rb +271 -0
  49. data/lib/mongoid/criteria/queryable/optional.rb +429 -0
  50. data/lib/mongoid/criteria/queryable/options.rb +153 -0
  51. data/lib/mongoid/criteria/queryable/pipeline.rb +111 -0
  52. data/lib/mongoid/criteria/queryable/selectable.rb +662 -0
  53. data/lib/mongoid/criteria/queryable/selector.rb +212 -0
  54. data/lib/mongoid/criteria/queryable/smash.rb +104 -0
  55. data/lib/mongoid/document.rb +30 -37
  56. data/lib/mongoid/errors.rb +2 -0
  57. data/lib/mongoid/errors/ambiguous_relationship.rb +1 -1
  58. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +1 -1
  59. data/lib/mongoid/errors/invalid_field.rb +2 -2
  60. data/lib/mongoid/errors/invalid_persistence_option.rb +29 -0
  61. data/lib/mongoid/errors/invalid_relation.rb +66 -0
  62. data/lib/mongoid/evolvable.rb +1 -1
  63. data/lib/mongoid/extensions.rb +0 -4
  64. data/lib/mongoid/extensions/big_decimal.rb +17 -8
  65. data/lib/mongoid/extensions/date.rb +4 -1
  66. data/lib/mongoid/extensions/decimal128.rb +3 -3
  67. data/lib/mongoid/extensions/hash.rb +1 -0
  68. data/lib/mongoid/extensions/string.rb +4 -3
  69. data/lib/mongoid/extensions/time.rb +4 -1
  70. data/lib/mongoid/fields/validators/macro.rb +18 -0
  71. data/lib/mongoid/findable.rb +2 -2
  72. data/lib/mongoid/indexable.rb +15 -13
  73. data/lib/mongoid/interceptable.rb +5 -22
  74. data/lib/mongoid/matchable.rb +13 -7
  75. data/lib/mongoid/matchable/all.rb +2 -2
  76. data/lib/mongoid/matchable/and.rb +3 -3
  77. data/lib/mongoid/matchable/default.rb +2 -2
  78. data/lib/mongoid/matchable/elem_match.rb +28 -0
  79. data/lib/mongoid/matchable/exists.rb +2 -2
  80. data/lib/mongoid/matchable/gt.rb +4 -2
  81. data/lib/mongoid/matchable/gte.rb +4 -2
  82. data/lib/mongoid/matchable/in.rb +2 -2
  83. data/lib/mongoid/matchable/lt.rb +4 -2
  84. data/lib/mongoid/matchable/lte.rb +4 -2
  85. data/lib/mongoid/matchable/ne.rb +2 -2
  86. data/lib/mongoid/matchable/nin.rb +2 -2
  87. data/lib/mongoid/matchable/or.rb +3 -3
  88. data/lib/mongoid/matchable/regexp.rb +3 -3
  89. data/lib/mongoid/matchable/size.rb +2 -2
  90. data/lib/mongoid/persistable.rb +3 -5
  91. data/lib/mongoid/persistable/creatable.rb +2 -2
  92. data/lib/mongoid/persistable/deletable.rb +1 -1
  93. data/lib/mongoid/persistable/settable.rb +1 -1
  94. data/lib/mongoid/persistable/updatable.rb +5 -12
  95. data/lib/mongoid/persistable/upsertable.rb +1 -1
  96. data/lib/mongoid/persistence_context.rb +215 -0
  97. data/lib/mongoid/query_cache.rb +3 -6
  98. data/lib/mongoid/relations/accessors.rb +3 -0
  99. data/lib/mongoid/relations/auto_save.rb +12 -4
  100. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +4 -4
  101. data/lib/mongoid/relations/counter_cache.rb +15 -5
  102. data/lib/mongoid/relations/eager.rb +6 -11
  103. data/lib/mongoid/relations/eager/base.rb +3 -3
  104. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +2 -2
  105. data/lib/mongoid/relations/eager/has_many.rb +1 -1
  106. data/lib/mongoid/relations/embedded/batchable.rb +12 -36
  107. data/lib/mongoid/relations/embedded/in.rb +13 -1
  108. data/lib/mongoid/relations/embedded/many.rb +28 -10
  109. data/lib/mongoid/relations/embedded/one.rb +14 -1
  110. data/lib/mongoid/relations/macros.rb +9 -1
  111. data/lib/mongoid/relations/metadata.rb +3 -3
  112. data/lib/mongoid/relations/options.rb +2 -2
  113. data/lib/mongoid/relations/proxy.rb +1 -31
  114. data/lib/mongoid/relations/referenced/in.rb +19 -10
  115. data/lib/mongoid/relations/referenced/many.rb +23 -17
  116. data/lib/mongoid/relations/referenced/many_to_many.rb +20 -13
  117. data/lib/mongoid/relations/referenced/one.rb +15 -1
  118. data/lib/mongoid/relations/synchronization.rb +11 -11
  119. data/lib/mongoid/relations/touchable.rb +6 -3
  120. data/lib/mongoid/reloadable.rb +1 -1
  121. data/lib/mongoid/serializable.rb +1 -1
  122. data/lib/mongoid/traversable.rb +1 -1
  123. data/lib/mongoid/validatable/uniqueness.rb +1 -2
  124. data/lib/mongoid/version.rb +1 -1
  125. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +14 -3
  126. data/spec/app/models/album.rb +5 -1
  127. data/spec/app/models/artist.rb +21 -0
  128. data/spec/app/models/book.rb +2 -1
  129. data/spec/app/models/dokument.rb +1 -0
  130. data/spec/app/models/ordered_post.rb +5 -0
  131. data/spec/app/models/oscar.rb +1 -2
  132. data/spec/app/models/page.rb +1 -1
  133. data/spec/app/models/person.rb +3 -3
  134. data/spec/app/models/princess.rb +2 -0
  135. data/spec/app/models/record.rb +1 -0
  136. data/spec/app/models/subscription.rb +1 -0
  137. data/spec/app/models/thing.rb +1 -1
  138. data/spec/config/mongoid.yml +15 -0
  139. data/spec/mongoid/atomic/modifiers_spec.rb +17 -17
  140. data/spec/mongoid/atomic_spec.rb +17 -17
  141. data/spec/mongoid/attributes/nested_spec.rb +14 -14
  142. data/spec/mongoid/attributes/readonly_spec.rb +87 -44
  143. data/spec/mongoid/attributes_spec.rb +90 -5
  144. data/spec/mongoid/cacheable_spec.rb +112 -0
  145. data/spec/mongoid/changeable_spec.rb +58 -0
  146. data/spec/mongoid/clients/factory_spec.rb +31 -3
  147. data/spec/mongoid/clients/options_spec.rb +382 -96
  148. data/spec/mongoid/clients_spec.rb +243 -101
  149. data/spec/mongoid/composable_spec.rb +7 -0
  150. data/spec/mongoid/config_spec.rb +67 -11
  151. data/spec/mongoid/contextual/atomic_spec.rb +3 -3
  152. data/spec/mongoid/contextual/mongo_spec.rb +165 -20
  153. data/spec/mongoid/contextual/none_spec.rb +15 -0
  154. data/spec/mongoid/copyable_spec.rb +13 -4
  155. data/spec/mongoid/criteria/modifiable_spec.rb +239 -7
  156. data/spec/mongoid/criteria/options_spec.rb +29 -0
  157. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +370 -0
  158. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +523 -0
  159. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +59 -0
  160. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +58 -0
  161. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +213 -0
  162. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +330 -0
  163. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +405 -0
  164. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +58 -0
  165. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +65 -0
  166. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +327 -0
  167. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +65 -0
  168. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +77 -0
  169. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +108 -0
  170. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +309 -0
  171. data/spec/mongoid/{extensions/origin → criteria/queryable/extensions}/regexp_raw_spec.rb +2 -2
  172. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +90 -0
  173. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +39 -0
  174. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +302 -0
  175. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +167 -0
  176. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +376 -0
  177. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +347 -0
  178. data/spec/mongoid/criteria/queryable/forwardable_spec.rb +87 -0
  179. data/spec/mongoid/criteria/queryable/key_spec.rb +52 -0
  180. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +49 -0
  181. data/spec/mongoid/criteria/queryable/optional_spec.rb +1799 -0
  182. data/spec/mongoid/criteria/queryable/options_spec.rb +360 -0
  183. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +200 -0
  184. data/spec/mongoid/criteria/queryable/queryable_spec.rb +137 -0
  185. data/spec/mongoid/criteria/queryable/selectable_spec.rb +4174 -0
  186. data/spec/mongoid/criteria/queryable/selector_spec.rb +844 -0
  187. data/spec/mongoid/criteria/queryable/smash_spec.rb +30 -0
  188. data/spec/mongoid/criteria_spec.rb +152 -21
  189. data/spec/mongoid/document_spec.rb +37 -88
  190. data/spec/mongoid/errors/invalid_relation_spec.rb +37 -0
  191. data/spec/mongoid/errors/mongoid_error_spec.rb +6 -3
  192. data/spec/mongoid/extensions/big_decimal_spec.rb +320 -18
  193. data/spec/mongoid/extensions/boolean_spec.rb +14 -0
  194. data/spec/mongoid/extensions/date_spec.rb +2 -6
  195. data/spec/mongoid/extensions/date_time_spec.rb +2 -6
  196. data/spec/mongoid/extensions/decimal128_spec.rb +1 -1
  197. data/spec/mongoid/extensions/float_spec.rb +8 -1
  198. data/spec/mongoid/extensions/hash_spec.rb +15 -0
  199. data/spec/mongoid/extensions/integer_spec.rb +8 -1
  200. data/spec/mongoid/extensions/object_spec.rb +11 -0
  201. data/spec/mongoid/extensions/string_spec.rb +21 -0
  202. data/spec/mongoid/extensions/time_spec.rb +2 -6
  203. data/spec/mongoid/extensions/time_with_zone_spec.rb +2 -6
  204. data/spec/mongoid/findable_spec.rb +46 -1
  205. data/spec/mongoid/indexable_spec.rb +15 -3
  206. data/spec/mongoid/interceptable_spec.rb +68 -10
  207. data/spec/mongoid/matchable/all_spec.rb +4 -4
  208. data/spec/mongoid/matchable/and_spec.rb +10 -10
  209. data/spec/mongoid/matchable/default_spec.rb +12 -12
  210. data/spec/mongoid/matchable/elem_match_spec.rb +86 -0
  211. data/spec/mongoid/matchable/exists_spec.rb +5 -5
  212. data/spec/mongoid/matchable/gt_spec.rb +18 -7
  213. data/spec/mongoid/matchable/gte_spec.rb +17 -7
  214. data/spec/mongoid/matchable/in_spec.rb +5 -5
  215. data/spec/mongoid/matchable/lt_spec.rb +18 -7
  216. data/spec/mongoid/matchable/lte_spec.rb +18 -7
  217. data/spec/mongoid/matchable/ne_spec.rb +5 -5
  218. data/spec/mongoid/matchable/nin_spec.rb +5 -5
  219. data/spec/mongoid/matchable/or_spec.rb +7 -7
  220. data/spec/mongoid/matchable/regexp_spec.rb +5 -5
  221. data/spec/mongoid/matchable/size_spec.rb +3 -3
  222. data/spec/mongoid/matchable_spec.rb +173 -53
  223. data/spec/mongoid/persistable/creatable_spec.rb +7 -2
  224. data/spec/mongoid/persistable/deletable_spec.rb +16 -1
  225. data/spec/mongoid/persistable/destroyable_spec.rb +6 -2
  226. data/spec/mongoid/persistable/savable_spec.rb +35 -30
  227. data/spec/mongoid/persistable/settable_spec.rb +45 -29
  228. data/spec/mongoid/persistable/updatable_spec.rb +184 -5
  229. data/spec/mongoid/persistence_context_spec.rb +680 -0
  230. data/spec/mongoid/positional_spec.rb +10 -10
  231. data/spec/mongoid/query_cache_spec.rb +89 -0
  232. data/spec/mongoid/relations/accessors_spec.rb +1 -1
  233. data/spec/mongoid/relations/auto_save_spec.rb +39 -6
  234. data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +4 -4
  235. data/spec/mongoid/relations/builders_spec.rb +37 -10
  236. data/spec/mongoid/relations/counter_cache_spec.rb +64 -3
  237. data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +16 -0
  238. data/spec/mongoid/relations/eager_spec.rb +40 -0
  239. data/spec/mongoid/relations/embedded/many_spec.rb +63 -47
  240. data/spec/mongoid/relations/embedded/one_spec.rb +2 -1
  241. data/spec/mongoid/relations/macros_spec.rb +395 -7
  242. data/spec/mongoid/relations/metadata_spec.rb +15 -1
  243. data/spec/mongoid/relations/proxy_spec.rb +27 -1
  244. data/spec/mongoid/relations/referenced/in_spec.rb +41 -1
  245. data/spec/mongoid/relations/referenced/many_spec.rb +13 -25
  246. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +14 -26
  247. data/spec/mongoid/relations/synchronization_spec.rb +48 -2
  248. data/spec/mongoid/relations/touchable_spec.rb +40 -0
  249. data/spec/mongoid/reloadable_spec.rb +51 -0
  250. data/spec/mongoid/serializable_spec.rb +0 -50
  251. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  252. data/spec/mongoid/validatable/uniqueness_spec.rb +18 -9
  253. data/spec/mongoid/validatable_spec.rb +16 -0
  254. data/spec/spec_helper.rb +20 -11
  255. metadata +524 -469
  256. checksums.yaml.gz.sig +0 -0
  257. data.tar.gz.sig +0 -0
  258. data/lib/mongoid/clients/thread_options.rb +0 -19
  259. data/lib/mongoid/extensions/origin/regexp_raw.rb +0 -43
  260. metadata.gz.sig +0 -0
@@ -0,0 +1,65 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ class Criteria
4
+ module Queryable
5
+
6
+ # Allows for easy delegation of queryable queryable instance methods to a
7
+ # specific method.
8
+ module Forwardable
9
+
10
+ # Tells queryable with method on the class to delegate to when calling an
11
+ # original selectable or optional method on the class.
12
+ #
13
+ # @example Tell queryable where to select from.
14
+ # class Band
15
+ # extend Queryable::Forwardable
16
+ # select_with :criteria
17
+ #
18
+ # def self.criteria
19
+ # Query.new
20
+ # end
21
+ # end
22
+ #
23
+ # @param [ Symbol ] receiver The name of the receiver method.
24
+ #
25
+ # @return [ Array<Symbol> ] The names of the forwarded methods.
26
+ #
27
+ # @since 1.0.0
28
+ def select_with(receiver)
29
+ (Selectable.forwardables + Optional.forwardables).each do |name|
30
+ __forward__(name, receiver)
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ # Forwards the method name to the provided receiver method.
37
+ #
38
+ # @api private
39
+ #
40
+ # @example Define the forwarding.
41
+ # Model.__forward__(:exists, :criteria)
42
+ #
43
+ # @param [ Symbol ] name The name of the method.
44
+ # @param [ Symbol ] receiver The name of the receiver method.
45
+ #
46
+ # @since 1.0.0
47
+ def __forward__(name, receiver)
48
+ if self.class == Module
49
+ module_eval <<-SEL, __FILE__, __LINE__ + 1
50
+ def #{name}(*args, &block)
51
+ #{receiver}.__send__(:#{name}, *args, &block)
52
+ end
53
+ SEL
54
+ else
55
+ singleton_class.class_eval <<-SEL, __FILE__, __LINE__ + 1
56
+ def #{name}(*args, &block)
57
+ #{receiver}.__send__(:#{name}, *args, &block)
58
+ end
59
+ SEL
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,103 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ class Criteria
4
+ module Queryable
5
+
6
+ # The key is a representation of a field in a queryable, that can be
7
+ # expanded to special MongoDB selectors.
8
+ class Key
9
+
10
+ # @attribute [r] name The name of the field.
11
+ # @attribute [r] block The optional block to transform values.
12
+ # @attribute [r] operator The MongoDB query operator.
13
+ # @attribute [r] expanded The MongoDB expanded query operator.
14
+ # @attribute [r] strategy The name of the merge strategy.
15
+ attr_reader :block, :name, :operator, :expanded, :strategy
16
+
17
+ # Does the key equal another object?
18
+ #
19
+ # @example Is the key equal to another?
20
+ # key == other
21
+ # key.eql? other
22
+ #
23
+ # @param [ Object ] other The object to compare to.
24
+ #
25
+ # @return [ true, false ] If the objects are equal.
26
+ #
27
+ # @since 1.0.0
28
+ def ==(other)
29
+ return false unless other.is_a?(Key)
30
+ name == other.name && operator == other.operator && expanded == other.expanded
31
+ end
32
+ alias :eql? :==
33
+
34
+ # Calculate the hash code for a key.
35
+ #
36
+ # @return [ Fixnum ] The hash code for the key.
37
+ #
38
+ # @since 1.1.0
39
+ def hash
40
+ [name, operator, expanded].hash
41
+ end
42
+
43
+ # Instantiate the new key.
44
+ #
45
+ # @example Instantiate the key.
46
+ # Key.new("age", "$gt")
47
+ #
48
+ # @param [ String, Symbol ] name The field name.
49
+ # @param [ Symbol ] strategy The name of the merge strategy.
50
+ # @param [ String ] operator The Mongo operator.
51
+ # @param [ String ] expanded The Mongo expanded operator.
52
+ #
53
+ # @since 1.0.0
54
+ def initialize(name, strategy, operator, expanded = nil, &block)
55
+ @name, @strategy, @operator, @expanded, @block =
56
+ name, strategy, operator, expanded, block
57
+ end
58
+
59
+ # Gets the raw selector that would be passed to Mongo from this key.
60
+ #
61
+ # @example Specify the raw selector.
62
+ # key.__expr_part__(50)
63
+ #
64
+ # @param [ Object ] object The value to be included.
65
+ # @param [ true, false ] negating If the selection should be negated.
66
+ #
67
+ # @return [ Hash ] The raw MongoDB selector.
68
+ #
69
+ # @since 1.0.0
70
+ def __expr_part__(object, negating = false)
71
+ value = block ? block[object] : object
72
+ expression = { operator => expanded ? { expanded => value } : value }
73
+ { name.to_s => (negating && operator != "$not") ? { "$not" => expression } : expression }
74
+ end
75
+
76
+ # Get the key as raw Mongo sorting options.
77
+ #
78
+ # @example Get the key as a sort.
79
+ # key.__sort_option__
80
+ #
81
+ # @return [ Hash ] The field/direction pair.
82
+ #
83
+ # @since 1.0.0
84
+ def __sort_option__
85
+ { name => operator }
86
+ end
87
+ alias :__sort_pair__ :__sort_option__
88
+
89
+ # Convert the key to a string.
90
+ #
91
+ # @example Convert the key to a string.
92
+ # key.to_s
93
+ #
94
+ # @return [ String ] The key as a string.
95
+ #
96
+ # @since 1.1.0
97
+ def to_s
98
+ @name.to_s
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ class Criteria
4
+ module Queryable
5
+
6
+ # Adds macro behaviour for adding symbol methods.
7
+ module Macroable
8
+
9
+ # Adds a method on Symbol for convenience in where queries for the
10
+ # provided operators.
11
+ #
12
+ # @example Add a symbol key.
13
+ # key :all, "$all
14
+ #
15
+ # @param [ Symbol ] name The name of the method.
16
+ # @param [ Symbol ] strategy The merge strategy.
17
+ # @param [ String ] operator The MongoDB operator.
18
+ # @param [ String ] additional The additional MongoDB operator.
19
+ #
20
+ # @since 1.0.0
21
+ def key(name, strategy, operator, additional = nil, &block)
22
+ ::Symbol.add_key(name, strategy, operator, additional, &block)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,271 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ class Criteria
4
+ module Queryable
5
+
6
+ # Contains behaviour for merging existing selection with new selection.
7
+ module Mergeable
8
+
9
+ # @attribute [rw] strategy The name of the current strategy.
10
+ attr_accessor :strategy
11
+
12
+ # Instruct the next mergeable call to use intersection.
13
+ #
14
+ # @example Use intersection on the next call.
15
+ # mergeable.intersect.in(field: [ 1, 2, 3 ])
16
+ #
17
+ # @return [ Mergeable ] The intersect flagged mergeable.
18
+ #
19
+ # @since 1.0.0
20
+ def intersect
21
+ use(:__intersect__)
22
+ end
23
+
24
+ # Instruct the next mergeable call to use override.
25
+ #
26
+ # @example Use override on the next call.
27
+ # mergeable.override.in(field: [ 1, 2, 3 ])
28
+ #
29
+ # @return [ Mergeable ] The override flagged mergeable.
30
+ #
31
+ # @since 1.0.0
32
+ def override
33
+ use(:__override__)
34
+ end
35
+
36
+ # Instruct the next mergeable call to use union.
37
+ #
38
+ # @example Use union on the next call.
39
+ # mergeable.union.in(field: [ 1, 2, 3 ])
40
+ #
41
+ # @return [ Mergeable ] The union flagged mergeable.
42
+ #
43
+ # @since 1.0.0
44
+ def union
45
+ use(:__union__)
46
+ end
47
+
48
+ # Reset the stratgies to nil, used after cloning.
49
+ #
50
+ # @example Reset the strategies.
51
+ # mergeable.reset_strategies!
52
+ #
53
+ # @return [ nil ] nil.
54
+ #
55
+ # @since 1.0.0
56
+ def reset_strategies!
57
+ self.strategy, self.negating = nil, nil
58
+ end
59
+
60
+ private
61
+
62
+ # Adds the criterion to the existing selection.
63
+ #
64
+ # @api private
65
+ #
66
+ # @example Add the criterion.
67
+ # mergeable.__add__({ name: 1 }, "$in")
68
+ #
69
+ # @param [ Hash ] criterion The criteria.
70
+ # @param [ String ] operator The MongoDB operator.
71
+ #
72
+ # @return [ Mergeable ] The new mergeable.
73
+ #
74
+ # @since 1.0.0
75
+ def __add__(criterion, operator)
76
+ with_strategy(:__add__, criterion, operator)
77
+ end
78
+
79
+ # Adds the criterion to the existing selection.
80
+ #
81
+ # @api private
82
+ #
83
+ # @example Add the criterion.
84
+ # mergeable.__expanded__([ 1, 10 ], "$within", "$center")
85
+ #
86
+ # @param [ Hash ] criterion The criteria.
87
+ # @param [ String ] outer The outer MongoDB operator.
88
+ # @param [ String ] inner The inner MongoDB operator.
89
+ #
90
+ # @return [ Mergeable ] The new mergeable.
91
+ #
92
+ # @since 1.0.0
93
+ def __expanded__(criterion, outer, inner)
94
+ selection(criterion) do |selector, field, value|
95
+ selector.store(field, { outer => { inner => value }})
96
+ end
97
+ end
98
+
99
+ # Perform a straight merge of the criterion into the selection and let the
100
+ # symbol overrides do all the work.
101
+ #
102
+ # @api private
103
+ #
104
+ # @example Straight merge the expanded criterion.
105
+ # mergeable.__merge__(location: [ 1, 10 ])
106
+ #
107
+ # @param [ Hash ] criterion The criteria.
108
+ #
109
+ # @return [ Mergeable ] The cloned object.
110
+ #
111
+ # @since 2.0.0
112
+ def __merge__(criterion)
113
+ selection(criterion) do |selector, field, value|
114
+ selector.merge!(field.__expr_part__(value))
115
+ end
116
+ end
117
+
118
+ # Adds the criterion to the existing selection.
119
+ #
120
+ # @api private
121
+ #
122
+ # @example Add the criterion.
123
+ # mergeable.__intersect__([ 1, 2 ], "$in")
124
+ #
125
+ # @param [ Hash ] criterion The criteria.
126
+ # @param [ String ] operator The MongoDB operator.
127
+ #
128
+ # @return [ Mergeable ] The new mergeable.
129
+ #
130
+ # @since 1.0.0
131
+ def __intersect__(criterion, operator)
132
+ with_strategy(:__intersect__, criterion, operator)
133
+ end
134
+
135
+ # Adds the criterion to the existing selection.
136
+ #
137
+ # @api private
138
+ #
139
+ # @example Add the criterion.
140
+ # mergeable.__multi__([ 1, 2 ], "$in")
141
+ #
142
+ # @param [ Hash ] criterion The criteria.
143
+ # @param [ String ] operator The MongoDB operator.
144
+ #
145
+ # @return [ Mergeable ] The new mergeable.
146
+ #
147
+ # @since 1.0.0
148
+ def __multi__(criterion, operator)
149
+ clone.tap do |query|
150
+ sel = query.selector
151
+ criterion.flatten.each do |expr|
152
+ next unless expr
153
+ criteria = sel[operator] || []
154
+ normalized = expr.inject({}) do |hash, (field, value)|
155
+ hash.merge!(field.__expr_part__(value.__expand_complex__))
156
+ hash
157
+ end
158
+ sel.store(operator, criteria.push(normalized))
159
+ end
160
+ end
161
+ end
162
+
163
+ # Adds the criterion to the existing selection.
164
+ #
165
+ # @api private
166
+ #
167
+ # @example Add the criterion.
168
+ # mergeable.__override__([ 1, 2 ], "$in")
169
+ #
170
+ # @param [ Hash ] criterion The criteria.
171
+ # @param [ String ] operator The MongoDB operator.
172
+ #
173
+ # @return [ Mergeable ] The new mergeable.
174
+ #
175
+ # @since 1.0.0
176
+ def __override__(criterion, operator)
177
+ selection(criterion) do |selector, field, value|
178
+ expression = prepare(field, operator, value)
179
+ existing = selector[field]
180
+ if existing.respond_to?(:merge!)
181
+ selector.store(field, existing.merge!(expression))
182
+ else
183
+ selector.store(field, expression)
184
+ end
185
+ end
186
+ end
187
+
188
+ # Adds the criterion to the existing selection.
189
+ #
190
+ # @api private
191
+ #
192
+ # @example Add the criterion.
193
+ # mergeable.__union__([ 1, 2 ], "$in")
194
+ #
195
+ # @param [ Hash ] criterion The criteria.
196
+ # @param [ String ] operator The MongoDB operator.
197
+ #
198
+ # @return [ Mergeable ] The new mergeable.
199
+ #
200
+ # @since 1.0.0
201
+ def __union__(criterion, operator)
202
+ with_strategy(:__union__, criterion, operator)
203
+ end
204
+
205
+ # Use the named strategy for the next operation.
206
+ #
207
+ # @api private
208
+ #
209
+ # @example Use intersection.
210
+ # mergeable.use(:__intersect__)
211
+ #
212
+ # @param [ Symbol ] strategy The strategy to use.
213
+ #
214
+ # @return [ Mergeable ] The existing mergeable.
215
+ #
216
+ # @since 1.0.0
217
+ def use(strategy)
218
+ tap do |mergeable|
219
+ mergeable.strategy = strategy
220
+ end
221
+ end
222
+
223
+ # Add criterion to the selection with the named strategy.
224
+ #
225
+ # @api private
226
+ #
227
+ # @example Add criterion with a strategy.
228
+ # mergeable.with_strategy(:__union__, [ 1, 2, 3 ], "$in")
229
+ #
230
+ # @param [ Symbol ] strategy The name of the strategy method.
231
+ # @param [ Object ] criterion The criterion to add.
232
+ # @param [ String ] operator The MongoDB operator.
233
+ #
234
+ # @return [ Mergeable ] The cloned query.
235
+ #
236
+ # @since 1.0.0
237
+ def with_strategy(strategy, criterion, operator)
238
+ selection(criterion) do |selector, field, value|
239
+ selector.store(
240
+ field,
241
+ selector[field].send(strategy, prepare(field, operator, value))
242
+ )
243
+ end
244
+ end
245
+
246
+ # Prepare the value for merging.
247
+ #
248
+ # @api private
249
+ #
250
+ # @example Prepare the value.
251
+ # mergeable.prepare("field", "$gt", 10)
252
+ #
253
+ # @param [ String ] field The name of the field.
254
+ # @param [ Object ] value The value.
255
+ #
256
+ # @return [ Object ] The serialized value.
257
+ #
258
+ # @since 1.0.0
259
+ def prepare(field, operator, value)
260
+ unless operator =~ /exists|type|size/
261
+ value = value.__expand_complex__
262
+ serializer = serializers[field]
263
+ value = serializer ? serializer.evolve(value) : value
264
+ end
265
+ selection = { operator => value }
266
+ negating? ? { "$not" => selection } : selection
267
+ end
268
+ end
269
+ end
270
+ end
271
+ end