mongoid 5.4.1 → 6.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (264) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/config/locales/en.yml +23 -16
  5. data/lib/mongoid.rb +4 -9
  6. data/lib/mongoid/atomic.rb +1 -1
  7. data/lib/mongoid/atomic/modifiers.rb +8 -12
  8. data/lib/mongoid/attributes.rb +9 -11
  9. data/lib/mongoid/attributes/dynamic.rb +5 -6
  10. data/lib/mongoid/attributes/nested.rb +1 -1
  11. data/lib/mongoid/attributes/processing.rb +4 -0
  12. data/lib/mongoid/attributes/readonly.rb +22 -0
  13. data/lib/mongoid/cacheable.rb +36 -0
  14. data/lib/mongoid/changeable.rb +37 -1
  15. data/lib/mongoid/clients.rb +0 -63
  16. data/lib/mongoid/clients/factory.rb +0 -2
  17. data/lib/mongoid/clients/options.rb +54 -249
  18. data/lib/mongoid/clients/storage_options.rb +1 -69
  19. data/lib/mongoid/composable.rb +26 -2
  20. data/lib/mongoid/config.rb +1 -1
  21. data/lib/mongoid/config/options.rb +1 -1
  22. data/lib/mongoid/contextual/aggregable/mongo.rb +1 -0
  23. data/lib/mongoid/contextual/atomic.rb +6 -9
  24. data/lib/mongoid/contextual/geo_near.rb +2 -3
  25. data/lib/mongoid/contextual/map_reduce.rb +97 -24
  26. data/lib/mongoid/contextual/memory.rb +7 -4
  27. data/lib/mongoid/contextual/mongo.rb +63 -54
  28. data/lib/mongoid/contextual/none.rb +2 -2
  29. data/lib/mongoid/copyable.rb +19 -19
  30. data/lib/mongoid/criteria.rb +5 -4
  31. data/lib/mongoid/criteria/findable.rb +2 -3
  32. data/lib/mongoid/criteria/includable.rb +63 -16
  33. data/lib/mongoid/criteria/marshalable.rb +2 -2
  34. data/lib/mongoid/criteria/modifiable.rb +17 -1
  35. data/lib/mongoid/criteria/options.rb +25 -0
  36. data/lib/mongoid/criteria/queryable.rb +86 -0
  37. data/lib/mongoid/criteria/queryable/aggregable.rb +120 -0
  38. data/lib/mongoid/criteria/queryable/extensions.rb +28 -0
  39. data/lib/mongoid/criteria/queryable/extensions/array.rb +185 -0
  40. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +37 -0
  41. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +34 -0
  42. data/lib/mongoid/criteria/queryable/extensions/date.rb +63 -0
  43. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +53 -0
  44. data/lib/mongoid/criteria/queryable/extensions/hash.rb +200 -0
  45. data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +86 -0
  46. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +90 -0
  47. data/lib/mongoid/criteria/queryable/extensions/object.rb +206 -0
  48. data/lib/mongoid/criteria/queryable/extensions/range.rb +70 -0
  49. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +45 -0
  50. data/lib/mongoid/criteria/queryable/extensions/set.rb +34 -0
  51. data/lib/mongoid/criteria/queryable/extensions/string.rb +137 -0
  52. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +79 -0
  53. data/lib/mongoid/criteria/queryable/extensions/time.rb +60 -0
  54. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +54 -0
  55. data/lib/mongoid/criteria/queryable/forwardable.rb +65 -0
  56. data/lib/mongoid/criteria/queryable/key.rb +103 -0
  57. data/lib/mongoid/criteria/queryable/macroable.rb +27 -0
  58. data/lib/mongoid/criteria/queryable/mergeable.rb +271 -0
  59. data/lib/mongoid/criteria/queryable/optional.rb +411 -0
  60. data/lib/mongoid/criteria/queryable/options.rb +136 -0
  61. data/lib/mongoid/criteria/queryable/pipeline.rb +111 -0
  62. data/lib/mongoid/criteria/queryable/selectable.rb +662 -0
  63. data/lib/mongoid/criteria/queryable/selector.rb +196 -0
  64. data/lib/mongoid/criteria/queryable/smash.rb +103 -0
  65. data/lib/mongoid/document.rb +9 -23
  66. data/lib/mongoid/errors.rb +2 -1
  67. data/lib/mongoid/errors/ambiguous_relationship.rb +1 -1
  68. data/lib/mongoid/errors/delete_restriction.rb +2 -2
  69. data/lib/mongoid/errors/invalid_field.rb +2 -2
  70. data/lib/mongoid/errors/invalid_persistence_option.rb +29 -0
  71. data/lib/mongoid/errors/invalid_relation.rb +66 -0
  72. data/lib/mongoid/errors/inverse_not_found.rb +1 -1
  73. data/lib/mongoid/errors/mongoid_error.rb +1 -1
  74. data/lib/mongoid/evolvable.rb +1 -1
  75. data/lib/mongoid/extensions.rb +0 -5
  76. data/lib/mongoid/extensions/big_decimal.rb +17 -8
  77. data/lib/mongoid/extensions/date.rb +4 -1
  78. data/lib/mongoid/extensions/hash.rb +2 -3
  79. data/lib/mongoid/extensions/object.rb +2 -2
  80. data/lib/mongoid/extensions/string.rb +4 -3
  81. data/lib/mongoid/extensions/time.rb +5 -2
  82. data/lib/mongoid/factory.rb +1 -0
  83. data/lib/mongoid/fields/foreign_key.rb +2 -2
  84. data/lib/mongoid/fields/localized.rb +3 -8
  85. data/lib/mongoid/fields/validators/macro.rb +18 -0
  86. data/lib/mongoid/findable.rb +3 -3
  87. data/lib/mongoid/indexable.rb +17 -16
  88. data/lib/mongoid/indexable/specification.rb +1 -1
  89. data/lib/mongoid/indexable/validators/options.rb +1 -2
  90. data/lib/mongoid/interceptable.rb +6 -17
  91. data/lib/mongoid/loggable.rb +1 -1
  92. data/lib/mongoid/matchable.rb +3 -10
  93. data/lib/mongoid/matchable/gt.rb +2 -0
  94. data/lib/mongoid/matchable/gte.rb +2 -0
  95. data/lib/mongoid/matchable/lt.rb +2 -0
  96. data/lib/mongoid/matchable/lte.rb +2 -0
  97. data/lib/mongoid/persistable.rb +6 -5
  98. data/lib/mongoid/persistable/creatable.rb +2 -0
  99. data/lib/mongoid/persistable/deletable.rb +7 -3
  100. data/lib/mongoid/persistable/settable.rb +3 -16
  101. data/lib/mongoid/persistable/updatable.rb +10 -12
  102. data/lib/mongoid/persistence_context.rb +216 -0
  103. data/lib/mongoid/query_cache.rb +5 -30
  104. data/lib/mongoid/relations/accessors.rb +6 -2
  105. data/lib/mongoid/relations/auto_save.rb +12 -4
  106. data/lib/mongoid/relations/bindings/embedded/in.rb +4 -0
  107. data/lib/mongoid/relations/bindings/embedded/many.rb +8 -1
  108. data/lib/mongoid/relations/bindings/embedded/one.rb +10 -0
  109. data/lib/mongoid/relations/bindings/referenced/many.rb +4 -0
  110. data/lib/mongoid/relations/builders.rb +2 -2
  111. data/lib/mongoid/relations/builders/embedded/one.rb +1 -1
  112. data/lib/mongoid/relations/builders/nested_attributes/many.rb +1 -1
  113. data/lib/mongoid/relations/conversions.rb +1 -1
  114. data/lib/mongoid/relations/counter_cache.rb +28 -18
  115. data/lib/mongoid/relations/eager.rb +19 -7
  116. data/lib/mongoid/relations/eager/base.rb +5 -5
  117. data/lib/mongoid/relations/embedded/batchable.rb +9 -33
  118. data/lib/mongoid/relations/embedded/in.rb +16 -2
  119. data/lib/mongoid/relations/embedded/many.rb +23 -8
  120. data/lib/mongoid/relations/embedded/one.rb +17 -2
  121. data/lib/mongoid/relations/macros.rb +9 -2
  122. data/lib/mongoid/relations/metadata.rb +3 -3
  123. data/lib/mongoid/relations/nested_builder.rb +1 -1
  124. data/lib/mongoid/relations/options.rb +2 -2
  125. data/lib/mongoid/relations/proxy.rb +2 -33
  126. data/lib/mongoid/relations/referenced/in.rb +23 -11
  127. data/lib/mongoid/relations/referenced/many.rb +24 -16
  128. data/lib/mongoid/relations/referenced/many_to_many.rb +20 -13
  129. data/lib/mongoid/relations/referenced/one.rb +17 -1
  130. data/lib/mongoid/relations/reflections.rb +3 -5
  131. data/lib/mongoid/relations/touchable.rb +1 -1
  132. data/lib/mongoid/reloadable.rb +1 -1
  133. data/lib/mongoid/scopable.rb +3 -3
  134. data/lib/mongoid/serializable.rb +2 -3
  135. data/lib/mongoid/tasks/database.rb +1 -2
  136. data/lib/mongoid/threaded.rb +4 -4
  137. data/lib/mongoid/traversable.rb +1 -1
  138. data/lib/mongoid/validatable.rb +1 -1
  139. data/lib/mongoid/validatable/macros.rb +2 -4
  140. data/lib/mongoid/validatable/uniqueness.rb +1 -2
  141. data/lib/mongoid/version.rb +1 -1
  142. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +4 -7
  143. data/spec/app/models/album.rb +5 -1
  144. data/spec/app/models/artist.rb +21 -0
  145. data/spec/app/models/band.rb +0 -1
  146. data/spec/app/models/church.rb +0 -2
  147. data/spec/app/models/ordered_post.rb +5 -0
  148. data/spec/app/models/oscar.rb +1 -2
  149. data/spec/app/models/person.rb +3 -1
  150. data/spec/app/models/post.rb +0 -1
  151. data/spec/app/models/princess.rb +2 -0
  152. data/spec/app/models/record.rb +1 -0
  153. data/spec/app/models/thing.rb +1 -1
  154. data/spec/config/mongoid.yml +1 -5
  155. data/spec/mongoid/atomic/modifiers_spec.rb +17 -17
  156. data/spec/mongoid/atomic_spec.rb +17 -17
  157. data/spec/mongoid/attributes/nested_spec.rb +14 -14
  158. data/spec/mongoid/attributes/readonly_spec.rb +87 -44
  159. data/spec/mongoid/attributes_spec.rb +63 -0
  160. data/spec/mongoid/cacheable_spec.rb +112 -0
  161. data/spec/mongoid/changeable_spec.rb +58 -0
  162. data/spec/mongoid/clients/factory_spec.rb +3 -11
  163. data/spec/mongoid/clients/options_spec.rb +378 -96
  164. data/spec/mongoid/clients_spec.rb +207 -170
  165. data/spec/mongoid/composable_spec.rb +7 -0
  166. data/spec/mongoid/config_spec.rb +41 -21
  167. data/spec/mongoid/contextual/atomic_spec.rb +77 -343
  168. data/spec/mongoid/contextual/map_reduce_spec.rb +119 -111
  169. data/spec/mongoid/contextual/memory_spec.rb +56 -316
  170. data/spec/mongoid/contextual/mongo_spec.rb +104 -378
  171. data/spec/mongoid/copyable_spec.rb +8 -15
  172. data/spec/mongoid/criteria/modifiable_spec.rb +239 -7
  173. data/spec/mongoid/criteria/options_spec.rb +29 -0
  174. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +370 -0
  175. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +523 -0
  176. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +59 -0
  177. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +58 -0
  178. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +213 -0
  179. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +330 -0
  180. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +405 -0
  181. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +58 -0
  182. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +65 -0
  183. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +327 -0
  184. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +65 -0
  185. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +77 -0
  186. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +108 -0
  187. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +309 -0
  188. data/spec/mongoid/{extensions/origin/regexp_raw_spec.rb → criteria/queryable/extensions/regexp_spec.rb} +21 -20
  189. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +39 -0
  190. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +302 -0
  191. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +167 -0
  192. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +376 -0
  193. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +347 -0
  194. data/spec/mongoid/criteria/queryable/forwardable_spec.rb +87 -0
  195. data/spec/mongoid/criteria/queryable/key_spec.rb +52 -0
  196. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +49 -0
  197. data/spec/mongoid/criteria/queryable/optional_spec.rb +1786 -0
  198. data/spec/mongoid/criteria/queryable/options_spec.rb +360 -0
  199. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +200 -0
  200. data/spec/mongoid/criteria/queryable/queryable_spec.rb +137 -0
  201. data/spec/mongoid/criteria/queryable/selectable_spec.rb +4159 -0
  202. data/spec/mongoid/criteria/queryable/selector_spec.rb +778 -0
  203. data/spec/mongoid/criteria/queryable/smash_spec.rb +30 -0
  204. data/spec/mongoid/criteria_spec.rb +45 -63
  205. data/spec/mongoid/document_spec.rb +21 -88
  206. data/spec/mongoid/errors/invalid_relation_spec.rb +37 -0
  207. data/spec/mongoid/errors/mongoid_error_spec.rb +6 -3
  208. data/spec/mongoid/extensions/big_decimal_spec.rb +320 -18
  209. data/spec/mongoid/extensions/date_spec.rb +2 -6
  210. data/spec/mongoid/extensions/date_time_spec.rb +2 -6
  211. data/spec/mongoid/extensions/float_spec.rb +8 -1
  212. data/spec/mongoid/extensions/integer_spec.rb +8 -1
  213. data/spec/mongoid/extensions/object_spec.rb +11 -0
  214. data/spec/mongoid/extensions/string_spec.rb +21 -0
  215. data/spec/mongoid/extensions/time_spec.rb +4 -8
  216. data/spec/mongoid/extensions/time_with_zone_spec.rb +2 -6
  217. data/spec/mongoid/fields/localized_spec.rb +0 -91
  218. data/spec/mongoid/findable_spec.rb +46 -1
  219. data/spec/mongoid/indexable_spec.rb +6 -46
  220. data/spec/mongoid/interceptable_spec.rb +49 -10
  221. data/spec/mongoid/matchable/gt_spec.rb +11 -0
  222. data/spec/mongoid/matchable/gte_spec.rb +10 -0
  223. data/spec/mongoid/matchable/lt_spec.rb +11 -0
  224. data/spec/mongoid/matchable/lte_spec.rb +11 -0
  225. data/spec/mongoid/matchable_spec.rb +1 -51
  226. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  227. data/spec/mongoid/persistable/deletable_spec.rb +1 -1
  228. data/spec/mongoid/persistable/destroyable_spec.rb +6 -2
  229. data/spec/mongoid/persistable/savable_spec.rb +30 -30
  230. data/spec/mongoid/persistable/settable_spec.rb +0 -185
  231. data/spec/mongoid/persistable/updatable_spec.rb +166 -5
  232. data/spec/mongoid/persistence_context_spec.rb +654 -0
  233. data/spec/mongoid/positional_spec.rb +10 -10
  234. data/spec/mongoid/query_cache_spec.rb +89 -65
  235. data/spec/mongoid/relations/accessors_spec.rb +1 -1
  236. data/spec/mongoid/relations/auto_save_spec.rb +39 -6
  237. data/spec/mongoid/relations/builders_spec.rb +37 -10
  238. data/spec/mongoid/relations/counter_cache_spec.rb +64 -15
  239. data/spec/mongoid/relations/cyclic_spec.rb +0 -22
  240. data/spec/mongoid/relations/embedded/many_spec.rb +9 -41
  241. data/spec/mongoid/relations/embedded/one_spec.rb +2 -1
  242. data/spec/mongoid/relations/macros_spec.rb +395 -7
  243. data/spec/mongoid/relations/proxy_spec.rb +3 -1
  244. data/spec/mongoid/relations/referenced/in_spec.rb +41 -1
  245. data/spec/mongoid/relations/referenced/many_spec.rb +6 -29
  246. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +6 -29
  247. data/spec/mongoid/relations/reflections_spec.rb +9 -9
  248. data/spec/mongoid/reloadable_spec.rb +51 -0
  249. data/spec/mongoid/scopable_spec.rb +0 -12
  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 +16 -9
  253. data/spec/mongoid/validatable_spec.rb +16 -0
  254. data/spec/spec_helper.rb +10 -10
  255. metadata +536 -479
  256. metadata.gz.sig +0 -0
  257. data/lib/mongoid/clients/thread_options.rb +0 -19
  258. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +0 -20
  259. data/lib/mongoid/extensions/decimal128.rb +0 -39
  260. data/lib/mongoid/extensions/origin/regexp_raw.rb +0 -43
  261. data/lib/mongoid/matchable/regexp.rb +0 -27
  262. data/spec/app/models/post_genre.rb +0 -6
  263. data/spec/mongoid/extensions/decimal128_spec.rb +0 -44
  264. data/spec/mongoid/matchable/regexp_spec.rb +0 -59
@@ -57,7 +57,7 @@ module Mongoid
57
57
  # @example Allow pluck for null context.
58
58
  # context.pluck(:name)
59
59
  #
60
- # @param [ String, Symbol, Array ] args Field or fields to pluck.
60
+ # @param [ String, Symbol, Array ] field or fields to pluck.
61
61
  #
62
62
  # @return [ Array ] Emtpy Array
63
63
  def pluck(*args)
@@ -69,7 +69,7 @@ module Mongoid
69
69
  # @example Create the new context.
70
70
  # Null.new(criteria)
71
71
  #
72
- # @param [ Criteria ] criteria The criteria.
72
+ # @param [ Criteria ] The criteria.
73
73
  #
74
74
  # @since 4.0.0
75
75
  def initialize(criteria)
@@ -14,17 +14,26 @@ module Mongoid
14
14
  # @example Clone the document.
15
15
  # document.clone
16
16
  #
17
+ # @param [ Document ] other The document getting cloned.
18
+ #
17
19
  # @return [ Document ] The new document.
18
20
  def clone
19
21
  # @note This next line is here to address #2704, even though having an
20
22
  # _id and id field in the document would cause problems with Mongoid
21
23
  # elsewhere.
22
24
  attrs = clone_document.except("_id", "id")
23
- begin
24
- self.class.new(attrs)
25
- rescue Errors::UnknownAttribute
26
- self.class.send(:include, Attributes::Dynamic)
27
- self.class.new(attrs)
25
+ dynamic_attrs = {}
26
+ attrs.reject! do |attr_name, value|
27
+ dynamic_attrs[attr_name] = value unless self.attribute_names.include?(attr_name)
28
+ end
29
+ self.class.new(attrs).tap do |object|
30
+ dynamic_attrs.each do |attr_name, value|
31
+ if object.respond_to?("#{attr_name}=")
32
+ object.send("#{attr_name}=", value)
33
+ else
34
+ object.attributes[attr_name] = value
35
+ end
36
+ end
28
37
  end
29
38
  end
30
39
  alias :dup :clone
@@ -38,10 +47,12 @@ module Mongoid
38
47
  # @example clone document
39
48
  # model.clone_document
40
49
  #
50
+ # @param [ Hash ] dcoument The document with hash format
51
+ #
41
52
  # @since 3.0.22
42
53
  def clone_document
43
54
  attrs = as_document.__deep_copy__
44
- process_localized_attributes(self, attrs)
55
+ process_localized_attributes(attrs)
45
56
  attrs
46
57
  end
47
58
 
@@ -56,23 +67,12 @@ module Mongoid
56
67
  # @param [ Hash ] attrs The attributes.
57
68
  #
58
69
  # @since 3.0.20
59
- def process_localized_attributes(klass, attrs)
60
- klass.localized_fields.keys.each do |name|
70
+ def process_localized_attributes(attrs)
71
+ localized_fields.keys.each do |name|
61
72
  if value = attrs.delete(name)
62
73
  attrs["#{name}_translations"] = value
63
74
  end
64
75
  end
65
- klass.embedded_relations.each do |_, metadata|
66
- next unless attrs.present? && attrs[metadata.key].present?
67
-
68
- if metadata.macro == :embeds_many
69
- attrs[metadata.key].each do |attr|
70
- process_localized_attributes(metadata.klass, attr)
71
- end
72
- else
73
- process_localized_attributes(metadata.klass, attrs[metadata.key])
74
- end
75
- end
76
76
  end
77
77
  end
78
78
  end
@@ -4,7 +4,9 @@ require "mongoid/criteria/includable"
4
4
  require "mongoid/criteria/inspectable"
5
5
  require "mongoid/criteria/marshalable"
6
6
  require "mongoid/criteria/modifiable"
7
+ require "mongoid/criteria/queryable"
7
8
  require "mongoid/criteria/scopable"
9
+ require "mongoid/criteria/options"
8
10
 
9
11
  module Mongoid
10
12
 
@@ -17,7 +19,7 @@ module Mongoid
17
19
  class Criteria
18
20
  include Enumerable
19
21
  include Contextual
20
- include Origin::Queryable
22
+ include Queryable
21
23
  include Findable
22
24
  include Inspectable
23
25
  include Includable
@@ -25,6 +27,7 @@ module Mongoid
25
27
  include Modifiable
26
28
  include Scopable
27
29
  include Clients::Options
30
+ include Options
28
31
 
29
32
  # Static array used to check with method missing - we only need to ever
30
33
  # instantiate once.
@@ -193,8 +196,6 @@ module Mongoid
193
196
  # @since 1.0.0
194
197
  def initialize(klass)
195
198
  @klass = klass
196
- @embedded = nil
197
- @none = nil
198
199
  klass ? super(klass.aliased_fields, klass.fields) : super({}, {})
199
200
  end
200
201
 
@@ -386,7 +387,7 @@ module Mongoid
386
387
  # @example Add a javascript selection.
387
388
  # criteria.where("this.name == 'syd'")
388
389
  #
389
- # @param [ String, Hash ] expression The javascript or standard selection.
390
+ # @param [ String, Hash ] criterion The javascript or standard selection.
390
391
  #
391
392
  # @raise [ UnsupportedJavascript ] If provided a string and the criteria
392
393
  # is embedded.
@@ -8,8 +8,7 @@ module Mongoid
8
8
  # @example Execute or raise
9
9
  # criteria.execute_or_raise(id)
10
10
  #
11
- # @param [ Object ] ids The arguments passed.
12
- # @param [ true, false ] multi Whether there arguments were a list.
11
+ # @param [ Object ] args The arguments passed.
13
12
  #
14
13
  # @raise [ Errors::DocumentNotFound ] If nothing returned.
15
14
  #
@@ -67,7 +66,7 @@ module Mongoid
67
66
  # @example Get the documents from the map or criteria.
68
67
  # criteria.multiple_from_map_or_db(ids)
69
68
  #
70
- # @param [ Array<Object> ] ids The searched ids.
69
+ # @param [ ids ] The searched ids.
71
70
  #
72
71
  # @return [ Array<Document> ] The found documents.
73
72
  def multiple_from_db(ids)
@@ -27,7 +27,13 @@ module Mongoid
27
27
  #
28
28
  # @since 2.2.0
29
29
  def includes(*relations)
30
- extract_includes_list(klass, relations)
30
+ relations.flatten.each do |relation|
31
+ if relation.is_a?(Hash)
32
+ extract_nested_inclusion(klass, relation)
33
+ else
34
+ add_inclusion(klass, relation)
35
+ end
36
+ end
31
37
  clone
32
38
  end
33
39
 
@@ -48,7 +54,7 @@ module Mongoid
48
54
  # @example Set the inclusions.
49
55
  # criteria.inclusions = [ meta ]
50
56
  #
51
- # @param [ Array<Metadata> ] value The inclusions.
57
+ # @param [ Array<Metadata> ] The inclusions.
52
58
  #
53
59
  # @return [ Array<Metadata> ] The new inclusions.
54
60
  #
@@ -65,31 +71,72 @@ module Mongoid
65
71
  # criteria.add_inclusion(Person, :posts)
66
72
  #
67
73
  # @param [ Class, String, Symbol ] _klass The class or string/symbol of the class name.
68
- # @param [ Symbol ] metadata The relation.
74
+ # @param [ Symbol ] relation The relation.
69
75
  #
70
76
  # @raise [ Errors::InvalidIncludes ] If no relation is found.
71
77
  #
72
78
  # @since 5.1.0
73
- def add_inclusion(_klass, metadata)
79
+ def add_inclusion(_klass, relation)
80
+ metadata = get_inclusion_metadata(_klass, relation)
81
+ raise Errors::InvalidIncludes.new(_klass, [ relation ]) unless metadata
74
82
  inclusions.push(metadata) unless inclusions.include?(metadata)
75
83
  end
76
84
 
77
- def extract_includes_list(_parent_class, *relations_list)
78
- relations_list.flatten.each do |relation_object|
79
- if relation_object.is_a?(Hash)
80
- relation_object.each do |relation, _includes|
81
- metadata = _parent_class.reflect_on_association(relation)
82
- raise Errors::InvalidIncludes.new(_klass, [ relation ]) unless metadata
83
- add_inclusion(_parent_class, metadata)
84
- extract_includes_list(metadata.klass, _includes)
85
- end
85
+ # Extract inclusion definitions from a list.
86
+ #
87
+ # @example Extract the inclusions from a list.
88
+ # criteria.extract_relations_list(:posts, [{ :alerts => :items }])
89
+ #
90
+ # @param [ Symbol ] association The name of the association.
91
+ # @param [ Array ] relations A list of associations.
92
+ #
93
+ # @since 5.1.0
94
+ def extract_relations_list(association, relations)
95
+ relations.each do |relation|
96
+ if relation.is_a?(Hash)
97
+ extract_nested_inclusion(association, relation)
86
98
  else
87
- metadata = _parent_class.reflect_on_association(relation_object)
88
- raise Errors::InvalidIncludes.new(_parent_class, [ relation_object ]) unless metadata
89
- add_inclusion(_parent_class, metadata)
99
+ add_inclusion(association, relation)
90
100
  end
91
101
  end
92
102
  end
103
+
104
+ # Extract nested inclusion.
105
+ #
106
+ # @example Extract the inclusions from a nested definition.
107
+ # criteria.extract_nested_inclusion(User, { :posts => [:alerts] })
108
+ #
109
+ # @param [ Class, Symbol ] _klass The class for which the inclusion should be added.
110
+ # @param [ Hash ] relation The nested inclusion.
111
+ #
112
+ # @since 5.1.0
113
+ def extract_nested_inclusion(_klass, relation)
114
+ relation.each do |association, _inclusion|
115
+ add_inclusion(_klass, association)
116
+ if _inclusion.is_a?(Array)
117
+ extract_relations_list(association, _inclusion)
118
+ else
119
+ add_inclusion(association, _inclusion)
120
+ end
121
+ end
122
+ end
123
+
124
+ # Get the metadata for an inclusion.
125
+ #
126
+ # @example Get the metadata for an inclusion definition.
127
+ # criteria.get_inclusion_metadata(User, :posts)
128
+ #
129
+ # @param [ Class, Symbol, String ] _klass The class for determining the association metadata
130
+ # @param [ Symbol ] association The name of the association.
131
+ #
132
+ # @since 5.1.0
133
+ def get_inclusion_metadata(_klass, association)
134
+ if _klass.is_a?(Class)
135
+ _klass.reflect_on_association(association)
136
+ else
137
+ _klass.to_s.classify.constantize.reflect_on_association(association)
138
+ end
139
+ end
93
140
  end
94
141
  end
95
142
  end
@@ -27,8 +27,8 @@ module Mongoid
27
27
  def marshal_load(data)
28
28
  @scoping_options, raw_selector, raw_options = data.pop(3)
29
29
  @klass, @driver, @inclusions, @documents, @strategy, @negating = data
30
- @selector = load_hash(Origin::Selector, raw_selector)
31
- @options = load_hash(Origin::Options, raw_options)
30
+ @selector = load_hash(Queryable::Selector, raw_selector)
31
+ @options = load_hash(Queryable::Options, raw_options)
32
32
  end
33
33
 
34
34
  private
@@ -173,7 +173,7 @@ module Mongoid
173
173
  # @since 3.0.0
174
174
  def create_document(method, attrs = nil, &block)
175
175
  attributes = selector.reduce(attrs ? attrs.dup : {}) do |hash, (key, value)|
176
- unless key.to_s =~ /\$/ || value.is_a?(Hash)
176
+ unless invalid_key?(hash, key) || invalid_embedded_doc?(value)
177
177
  hash[key] = value
178
178
  end
179
179
  hash
@@ -216,6 +216,22 @@ module Mongoid
216
216
  def first_or(method, attrs = {}, &block)
217
217
  first || create_document(method, attrs, &block)
218
218
  end
219
+
220
+ private
221
+
222
+ def invalid_key?(hash, key)
223
+ # @todo Change this to BSON::String::ILLEGAL_KEY when ruby driver 2.3.0 is
224
+ # released and mongoid is updated to depend on driver >= 2.3.0
225
+ key.to_s =~ Mongoid::Document::ILLEGAL_KEY || hash.key?(key.to_sym) || hash.key?(key)
226
+ end
227
+
228
+ def invalid_embedded_doc?(value)
229
+ # @todo Change this to BSON::String::ILLEGAL_KEY when ruby driver 2.3.0 is
230
+ # released and mongoid is updated to depend on driver >= 2.3.0
231
+ value.is_a?(Hash) && value.any? do |key, v|
232
+ key.to_s =~ Mongoid::Document::ILLEGAL_KEY || invalid_embedded_doc?(v)
233
+ end
234
+ end
219
235
  end
220
236
  end
221
237
  end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ class Criteria
4
+
5
+ # Module containing functionality for getting options on a Criteria object.
6
+ #
7
+ # @since 6.0.0
8
+ module Options
9
+
10
+ private
11
+
12
+ def persistence_context
13
+ klass.persistence_context
14
+ end
15
+
16
+ def set_persistence_context(options)
17
+ PersistenceContext.set(klass, options)
18
+ end
19
+
20
+ def clear_persistence_context(original_cluster)
21
+ PersistenceContext.clear(klass, original_cluster)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,86 @@
1
+ # encoding: utf-8
2
+ require "mongoid/criteria/queryable/extensions"
3
+ require "mongoid/criteria/queryable/forwardable"
4
+ require "mongoid/criteria/queryable/key"
5
+ require "mongoid/criteria/queryable/macroable"
6
+ require "mongoid/criteria/queryable/mergeable"
7
+ require "mongoid/criteria/queryable/smash"
8
+ require "mongoid/criteria/queryable/aggregable"
9
+ require "mongoid/criteria/queryable/pipeline"
10
+ require "mongoid/criteria/queryable/optional"
11
+ require "mongoid/criteria/queryable/options"
12
+ require "mongoid/criteria/queryable/selectable"
13
+ require "mongoid/criteria/queryable/selector"
14
+
15
+ module Mongoid
16
+ class Criteria
17
+
18
+ # A queryable is any object that needs queryable's dsl injected into it to build
19
+ # MongoDB queries. For example, a Mongoid::Criteria is an Queryable.
20
+ #
21
+ # @example Include queryable functionality.
22
+ # class Criteria
23
+ # include Queryable
24
+ # end
25
+ module Queryable
26
+ include Mergeable
27
+ include Aggregable
28
+ include Selectable
29
+ include Optional
30
+
31
+ # @attribute [r] aliases The aliases.
32
+ # @attribute [r] driver The Mongo driver being used.
33
+ # @attribute [r] serializers The serializers.
34
+ attr_reader :aliases, :driver, :serializers
35
+
36
+ # Is this queryable equal to another object? Is true if the selector and
37
+ # options are equal.
38
+ #
39
+ # @example Are the objects equal?
40
+ # queryable == criteria
41
+ #
42
+ # @param [ Object ] other The object to compare against.
43
+ #
44
+ # @return [ true, false ] If the objects are equal.
45
+ #
46
+ # @since 1.0.0
47
+ def ==(other)
48
+ return false unless other.is_a?(Queryable)
49
+ selector == other.selector && options == other.options
50
+ end
51
+
52
+ # Initialize the new queryable. Will yield itself to the block if a block
53
+ # is provided for objects that need additional behaviour.
54
+ #
55
+ # @example Initialize the queryable.
56
+ # Queryable.new
57
+ #
58
+ # @param [ Hash ] aliases The optional field aliases.
59
+ # @param [ Hash ] serializers The optional field serializers.
60
+ # @param [ Symbol ] driver The driver being used.
61
+ #
62
+ # @since 1.0.0
63
+ def initialize(aliases = {}, serializers = {}, driver = :mongo)
64
+ @aliases, @driver, @serializers = aliases, driver.to_sym, serializers
65
+ @options = Options.new(aliases, serializers)
66
+ @selector = Selector.new(aliases, serializers)
67
+ @pipeline = Pipeline.new(aliases)
68
+ yield(self) if block_given?
69
+ end
70
+
71
+ # Handle the creation of a copy via #clone or #dup.
72
+ #
73
+ # @example Handle copy initialization.
74
+ # queryable.initialize_copy(criteria)
75
+ #
76
+ # @param [ Queryable ] other The original copy.
77
+ #
78
+ # @since 1.0.0
79
+ def initialize_copy(other)
80
+ @options = other.options.__deep_copy__
81
+ @selector = other.selector.__deep_copy__
82
+ @pipeline = other.pipeline.__deep_copy__
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,120 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ class Criteria
4
+ module Queryable
5
+
6
+ # Provides a DSL around crafting aggregation framework commands.
7
+ #
8
+ # @since 2.0.0
9
+ module Aggregable
10
+ extend Macroable
11
+
12
+ # @attribute [r] pipeline The aggregation pipeline.
13
+ attr_reader :pipeline
14
+
15
+ # @attribute [rw] aggregating Flag for whether or not we are aggregating.
16
+ attr_writer :aggregating
17
+
18
+ # Has the aggregable enter an aggregation state. Ie, are only aggregation
19
+ # operations allowed at this point on.
20
+ #
21
+ # @example Is the aggregable aggregating?
22
+ # aggregable.aggregating?
23
+ #
24
+ # @return [ true, false ] If the aggregable is aggregating.
25
+ #
26
+ # @since 2.0.0
27
+ def aggregating?
28
+ !!@aggregating
29
+ end
30
+
31
+ # Add a group ($group) operation to the aggregation pipeline.
32
+ #
33
+ # @example Add a group operation being verbose.
34
+ # aggregable.group(count: { "$sum" => 1 }, max: { "$max" => "likes" })
35
+ #
36
+ # @example Add a group operation using symbol shortcuts.
37
+ # aggregable.group(:count.sum => 1, :max.max => "likes")
38
+ #
39
+ # @param [ Hash ] operation The group operation.
40
+ #
41
+ # @return [ Aggregable ] The aggregable.
42
+ #
43
+ # @since 2.0.0
44
+ def group(operation)
45
+ aggregation(operation) do |pipeline|
46
+ pipeline.group(operation)
47
+ end
48
+ end
49
+ key :avg, :override, "$avg"
50
+ key :max, :override, "$max"
51
+ key :min, :override, "$min"
52
+ key :sum, :override, "$sum"
53
+ key :last, :override, "$last"
54
+ key :push, :override, "$push"
55
+ key :first, :override, "$first"
56
+ key :add_to_set, :override, "$addToSet"
57
+
58
+ # Add a projection ($project) to the aggregation pipeline.
59
+ #
60
+ # @example Add a projection to the pipeline.
61
+ # aggregable.project(author: 1, name: 0)
62
+ #
63
+ # @param [ Hash ] criterion The projection to make.
64
+ #
65
+ # @return [ Aggregable ] The aggregable.
66
+ #
67
+ # @since 2.0.0
68
+ def project(operation = nil)
69
+ aggregation(operation) do |pipeline|
70
+ pipeline.project(operation)
71
+ end
72
+ end
73
+
74
+ # Add an unwind ($unwind) to the aggregation pipeline.
75
+ #
76
+ # @example Add an unwind to the pipeline.
77
+ # aggregable.unwind(:field)
78
+ #
79
+ # @param [ String, Symbol ] field The name of the field to unwind.
80
+ #
81
+ # @return [ Aggregable ] The aggregable.
82
+ #
83
+ # @since 2.0.0
84
+ def unwind(field)
85
+ aggregation(field) do |pipeline|
86
+ pipeline.unwind(field)
87
+ end
88
+ end
89
+
90
+ private
91
+
92
+ # Add the aggregation operation.
93
+ #
94
+ # @api private
95
+ #
96
+ # @example Aggregate on the operation.
97
+ # aggregation(operation) do |pipeline|
98
+ # pipeline.push("$project" => operation)
99
+ # end
100
+ #
101
+ # @param [ Hash ] operation The operation for the pipeline.
102
+ #
103
+ # @return [ Aggregable ] The cloned aggregable.
104
+ #
105
+ # @since 2.0.0
106
+ def aggregation(operation)
107
+ return self unless operation
108
+ clone.tap do |query|
109
+ unless aggregating?
110
+ query.pipeline.concat(query.selector.to_pipeline)
111
+ query.pipeline.concat(query.options.to_pipeline)
112
+ query.aggregating = true
113
+ end
114
+ yield(query.pipeline)
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end