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,212 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ class Criteria
4
+ module Queryable
5
+
6
+ # The selector is a special kind of hash that knows how to serialize values
7
+ # coming into it as well as being alias and locale aware for key names.
8
+ class Selector < Smash
9
+
10
+ # Merges another selector into this one.
11
+ #
12
+ # @example Merge in another selector.
13
+ # selector.merge!(name: "test")
14
+ #
15
+ # @param [ Hash, Selector ] other The object to merge in.
16
+ #
17
+ # @return [ Selector ] The selector.
18
+ #
19
+ # @since 1.0.0
20
+ def merge!(other)
21
+ other.each_pair do |key, value|
22
+ if value.is_a?(Hash) && self[key.to_s].is_a?(Hash)
23
+ value = self[key.to_s].merge(value) do |_key, old_val, new_val|
24
+ if in?(_key)
25
+ new_val & old_val
26
+ elsif nin?(_key)
27
+ (old_val + new_val).uniq
28
+ else
29
+ new_val
30
+ end
31
+ end
32
+ end
33
+ if multi_selection?(key)
34
+ value = (self[key.to_s] || []).concat(value)
35
+ end
36
+ store(key, value)
37
+ end
38
+ end
39
+
40
+ # Store the value in the selector for the provided key. The selector will
41
+ # handle all necessary serialization and localization in this step.
42
+ #
43
+ # @example Store a value in the selector.
44
+ # selector.store(:key, "testing")
45
+ #
46
+ # @param [ String, Symbol ] key The name of the attribute.
47
+ # @param [ Object ] value The value to add.
48
+ #
49
+ # @return [ Object ] The stored object.
50
+ #
51
+ # @since 1.0.0
52
+ def store(key, value)
53
+ name, serializer = storage_pair(key)
54
+ if multi_selection?(name)
55
+ super(name, evolve_multi(value))
56
+ else
57
+ super(localized_key(name, serializer), evolve(serializer, value))
58
+ end
59
+ end
60
+ alias :[]= :store
61
+
62
+ # Convert the selector to an aggregation pipeline entry.
63
+ #
64
+ # @example Convert the selector to a pipeline.
65
+ # selector.to_pipeline
66
+ #
67
+ # @return [ Array<Hash> ] The pipeline entry for the selector.
68
+ #
69
+ # @since 2.0.0
70
+ def to_pipeline
71
+ pipeline = []
72
+ pipeline.push({ "$match" => self }) unless empty?
73
+ pipeline
74
+ end
75
+
76
+ private
77
+
78
+ # Evolves a multi-list selection, like an $and or $or criterion, and
79
+ # performs the necessary serialization.
80
+ #
81
+ # @api private
82
+ #
83
+ # @example Evolve the multi-selection.
84
+ # selector.evolve_multi([{ field: "value" }])
85
+ #
86
+ # @param [ Array<Hash> ] value The multi-selection.
87
+ #
88
+ # @return [ Array<Hash> ] The serialized values.
89
+ #
90
+ # @since 1.0.0
91
+ def evolve_multi(value)
92
+ value.map do |val|
93
+ Hash[val.map do |key, _value|
94
+ _value = evolve_multi(_value) if multi_selection?(key)
95
+ name, serializer = storage_pair(key)
96
+ [ localized_key(name, serializer), evolve(serializer, _value) ]
97
+ end]
98
+ end.uniq
99
+ end
100
+
101
+ # Evolve a single key selection with various types of values.
102
+ #
103
+ # @api private
104
+ #
105
+ # @example Evolve a simple selection.
106
+ # selector.evolve(field, 5)
107
+ #
108
+ # @param [ Object ] serializer The optional serializer for the field.
109
+ # @param [ Object ] value The value to serialize.
110
+ #
111
+ # @return [ Object ] The serialized object.
112
+ #
113
+ # @since 1.0.0
114
+ def evolve(serializer, value)
115
+ case value
116
+ when Hash
117
+ evolve_hash(serializer, value)
118
+ when Array
119
+ evolve_array(serializer, value)
120
+ else
121
+ (serializer || value.class).evolve(value)
122
+ end
123
+ end
124
+
125
+ # Evolve a single key selection with array values.
126
+ #
127
+ # @api private
128
+ #
129
+ # @example Evolve a simple selection.
130
+ # selector.evolve(field, [ 1, 2, 3 ])
131
+ #
132
+ # @param [ Object ] serializer The optional serializer for the field.
133
+ # @param [ Array<Object> ] value The array to serialize.
134
+ #
135
+ # @return [ Object ] The serialized array.
136
+ #
137
+ # @since 1.0.0
138
+ def evolve_array(serializer, value)
139
+ value.map do |_value|
140
+ evolve(serializer, _value)
141
+ end
142
+ end
143
+
144
+ # Evolve a single key selection with hash values.
145
+ #
146
+ # @api private
147
+ #
148
+ # @example Evolve a simple selection.
149
+ # selector.evolve(field, { "$gt" => 5 })
150
+ #
151
+ # @param [ Object ] serializer The optional serializer for the field.
152
+ # @param [ Hash ] value The hash to serialize.
153
+ #
154
+ # @return [ Object ] The serialized hash.
155
+ #
156
+ # @since 1.0.0
157
+ def evolve_hash(serializer, value)
158
+ value.each_pair do |operator, _value|
159
+ if operator =~ /exists|type|size/
160
+ value[operator] = _value
161
+ else
162
+ value[operator] = evolve(serializer, _value)
163
+ end
164
+ end
165
+ end
166
+
167
+ # Determines if the selection is a multi-select, like an $and or $or or $nor
168
+ # selection.
169
+ #
170
+ # @api private
171
+ #
172
+ # @example Is the selection a multi-select?
173
+ # selector.multi_selection?("$and")
174
+ #
175
+ # @param [ String ] key The key to check.
176
+ #
177
+ # @return [ true, false ] If the key is for a multi-select.
178
+ #
179
+ # @since 1.0.0
180
+ def multi_selection?(key)
181
+ key =~ /\$and|\$or|\$nor/
182
+ end
183
+
184
+ # Determines if the selection operator takes a list. Returns true for $in and $nin.
185
+ #
186
+ # @api private
187
+ #
188
+ # @example Does the selection operator take multiple values?
189
+ # selector.multi_value?("$nin")
190
+ #
191
+ # @param [ String ] key The key to check.
192
+ #
193
+ # @return [ true, false ] If the key is $in or $nin.
194
+ #
195
+ # @since 2.1.1
196
+ def multi_value?(key)
197
+ key =~ /\$nin|\$in/
198
+ end
199
+
200
+ private
201
+
202
+ def in?(key)
203
+ key =~ /\$in/
204
+ end
205
+
206
+ def nin?(key)
207
+ key =~ /\$nin/
208
+ end
209
+ end
210
+ end
211
+ end
212
+ end
@@ -0,0 +1,104 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ class Criteria
4
+ module Queryable
5
+
6
+ # This is a smart hash for use with options and selectors.
7
+ class Smash < Hash
8
+
9
+ # @attribute [r] aliases The aliases.
10
+ # @attribute [r] serializers The serializers.
11
+ attr_reader :aliases, :serializers
12
+
13
+ # Perform a deep copy of the smash.
14
+ #
15
+ # @example Perform a deep copy.
16
+ # smash.__deep_copy__
17
+ #
18
+ # @return [ Smash ] The copied hash.
19
+ #
20
+ # @since 1.0.0
21
+ def __deep_copy__
22
+ self.class.new(aliases, serializers) do |copy|
23
+ each_pair do |key, value|
24
+ copy.store(key, value.__deep_copy__)
25
+ end
26
+ end
27
+ end
28
+
29
+ # Initialize the new selector.
30
+ #
31
+ # @example Initialize the new selector.
32
+ # Queryable::Smash.new(aliases, serializers)
33
+ #
34
+ # @param [ Hash ] aliases A hash of mappings from aliases to the actual
35
+ # field names in the database.
36
+ # @param [ Hash ] serializers An optional hash of objects that are
37
+ # responsible for serializing values. The keys of the hash must be
38
+ # strings that match the field name, and the values must respond to
39
+ # #localized? and #evolve(object).
40
+ #
41
+ # @since 1.0.0
42
+ def initialize(aliases = {}, serializers = {})
43
+ @aliases, @serializers = aliases, serializers
44
+ yield(self) if block_given?
45
+ end
46
+
47
+ # Get an item from the smart hash by the provided key.
48
+ #
49
+ # @example Get an item by the key.
50
+ # smash["test"]
51
+ #
52
+ # @param [ String ] key The key.
53
+ #
54
+ # @return [ Object ] The found object.
55
+ #
56
+ # @since 2.0.0
57
+ def [](key)
58
+ fetch(aliases[key]) { super }
59
+ end
60
+
61
+ private
62
+
63
+ # Get the localized value for the key if needed. If the field uses
64
+ # localization the current locale will be appended to the key in
65
+ # MongoDB dot notation.
66
+ #
67
+ # @api private
68
+ #
69
+ # @example Get the normalized key name.
70
+ # smash.localized_key("field", serializer)
71
+ #
72
+ # @param [ String ] name The name of the field.
73
+ # @param [ Object ] serializer The optional field serializer.
74
+ #
75
+ # @return [ String ] The normalized key.
76
+ #
77
+ # @since 1.0.0
78
+ def localized_key(name, serializer)
79
+ serializer && serializer.localized? ? "#{name}.#{::I18n.locale}" : name
80
+ end
81
+
82
+ # Get the pair of objects needed to store the value in a hash by the
83
+ # provided key. This is the database field name and the serializer.
84
+ #
85
+ # @api private
86
+ #
87
+ # @example Get the name and serializer.
88
+ # smash.storage_pair("id")
89
+ #
90
+ # @param [ Symbol, String ] key The key provided to the selection.
91
+ #
92
+ # @return [ Array<String, Object> ] The name of the db field and
93
+ # serializer.
94
+ #
95
+ # @since 1.0.0
96
+ def storage_pair(key)
97
+ field = key.to_s
98
+ name = aliases[field] || field
99
+ [ name, serializers[name] ]
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -31,6 +31,15 @@ module Mongoid
31
31
  Mongoid.register_model(self)
32
32
  end
33
33
 
34
+ # Regex for matching illegal BSON keys.
35
+ # Note that bson 4.1 has the constant BSON::String::ILLEGAL_KEY
36
+ # that should be used instead.
37
+ # When ruby driver 2.3.0 is released and Mongoid can be updated
38
+ # to require >= 2.3.0, the BSON constant can be used.
39
+ #
40
+ # @since 6.0.0
41
+ ILLEGAL_KEY = /(\A[$])|(\.)/.freeze
42
+
34
43
  # Freezes the internal attributes of the document.
35
44
  #
36
45
  # @example Freeze the document
@@ -40,7 +49,7 @@ module Mongoid
40
49
  #
41
50
  # @since 2.0.0
42
51
  def freeze
43
- as_document.freeze and self
52
+ as_attributes.freeze and self
44
53
  end
45
54
 
46
55
  # Checks if the document is frozen
@@ -105,7 +114,6 @@ module Mongoid
105
114
  _building do
106
115
  @new_record = true
107
116
  @attributes ||= {}
108
- with(self.class.persistence_options)
109
117
  apply_pre_processed_defaults
110
118
  apply_default_scoping
111
119
  process_attributes(attrs) do
@@ -165,20 +173,7 @@ module Mongoid
165
173
  #
166
174
  # @since 1.0.0
167
175
  def as_document
168
- return attributes if frozen?
169
- embedded_relations.each_pair do |name, meta|
170
- without_autobuild do
171
- relation, stored = send(name), meta.store_as
172
- if attributes.key?(stored) || !relation.blank?
173
- if relation
174
- attributes[stored] = relation.as_document
175
- else
176
- attributes.delete(stored)
177
- end
178
- end
179
- end
180
- end
181
- attributes
176
+ BSON::Document.new(as_attributes)
182
177
  end
183
178
 
184
179
  # Calls #as_json on the document with additional, Mongoid-specific options.
@@ -243,27 +238,6 @@ module Mongoid
243
238
  became
244
239
  end
245
240
 
246
- # Print out the cache key. This will append different values on the
247
- # plural model name.
248
- #
249
- # If new_record? - will append /new
250
- # If not - will append /id-updated_at.to_s(:nsec)
251
- # Without updated_at - will append /id
252
- #
253
- # This is usually called insode a cache() block
254
- #
255
- # @example Returns the cache key
256
- # document.cache_key
257
- #
258
- # @return [ String ] the string with or without updated_at
259
- #
260
- # @since 2.4.0
261
- def cache_key
262
- return "#{model_key}/new" if new_record?
263
- return "#{model_key}/#{id}-#{updated_at.utc.to_s(:nsec)}" if do_or_do_not(:updated_at)
264
- "#{model_key}/#{id}"
265
- end
266
-
267
241
  private
268
242
 
269
243
  # Returns the logger
@@ -299,6 +273,25 @@ module Mongoid
299
273
  nil
300
274
  end
301
275
 
276
+ private
277
+
278
+ def as_attributes
279
+ return attributes if frozen?
280
+ embedded_relations.each_pair do |name, meta|
281
+ without_autobuild do
282
+ relation, stored = send(name), meta.store_as
283
+ if attributes.key?(stored) || !relation.blank?
284
+ if relation
285
+ attributes[stored] = relation.send(:as_attributes)
286
+ else
287
+ attributes.delete(stored)
288
+ end
289
+ end
290
+ end
291
+ end
292
+ attributes
293
+ end
294
+
302
295
  module ClassMethods
303
296
 
304
297
  # Performs class equality checking.
@@ -15,6 +15,8 @@ require "mongoid/errors/invalid_includes"
15
15
  require "mongoid/errors/invalid_index"
16
16
  require "mongoid/errors/invalid_options"
17
17
  require "mongoid/errors/invalid_path"
18
+ require "mongoid/errors/invalid_persistence_option"
19
+ require "mongoid/errors/invalid_relation"
18
20
  require "mongoid/errors/invalid_scope"
19
21
  require "mongoid/errors/invalid_set_polymorphic_relation"
20
22
  require "mongoid/errors/invalid_storage_options"
@@ -24,7 +24,7 @@ module Mongoid
24
24
  #
25
25
  # @example Create the error.
26
26
  # AmbiguousRelationship.new(
27
- # Person, Drug, :person, [ :drugs, # :evil_drugs ]
27
+ # Person, Drug, :person, [ :drugs, :evil_drugs ]
28
28
  # )
29
29
  #
30
30
  # @param [ Class ] klass The base class.
@@ -11,7 +11,7 @@ module Mongoid
11
11
  # @example Create the new unsupported collation error.
12
12
  # InMemoryCollationNotSupported.new
13
13
  #
14
- # @since 5.2.0
14
+ # @since 6.1.0
15
15
  def initialize
16
16
  super(compose_message("in_memory_collation_not_supported"))
17
17
  end