mongoid-multi-db 3.0.0

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 (276) hide show
  1. data/CHANGELOG.md +615 -0
  2. data/LICENSE +20 -0
  3. data/README.md +62 -0
  4. data/Rakefile +49 -0
  5. data/lib/config/locales/bg.yml +54 -0
  6. data/lib/config/locales/de.yml +54 -0
  7. data/lib/config/locales/en-GB.yml +55 -0
  8. data/lib/config/locales/en.yml +55 -0
  9. data/lib/config/locales/es.yml +52 -0
  10. data/lib/config/locales/fr.yml +55 -0
  11. data/lib/config/locales/hi.yml +46 -0
  12. data/lib/config/locales/hu.yml +57 -0
  13. data/lib/config/locales/id.yml +55 -0
  14. data/lib/config/locales/it.yml +52 -0
  15. data/lib/config/locales/ja.yml +50 -0
  16. data/lib/config/locales/kr.yml +47 -0
  17. data/lib/config/locales/nl.yml +52 -0
  18. data/lib/config/locales/pl.yml +52 -0
  19. data/lib/config/locales/pt-BR.yml +53 -0
  20. data/lib/config/locales/pt.yml +53 -0
  21. data/lib/config/locales/ro.yml +59 -0
  22. data/lib/config/locales/ru.yml +54 -0
  23. data/lib/config/locales/sv.yml +53 -0
  24. data/lib/config/locales/vi.yml +55 -0
  25. data/lib/config/locales/zh-CN.yml +46 -0
  26. data/lib/mongoid.rb +148 -0
  27. data/lib/mongoid/atomic.rb +230 -0
  28. data/lib/mongoid/atomic/modifiers.rb +243 -0
  29. data/lib/mongoid/atomic/paths.rb +3 -0
  30. data/lib/mongoid/atomic/paths/embedded.rb +43 -0
  31. data/lib/mongoid/atomic/paths/embedded/many.rb +44 -0
  32. data/lib/mongoid/atomic/paths/embedded/one.rb +43 -0
  33. data/lib/mongoid/atomic/paths/root.rb +40 -0
  34. data/lib/mongoid/attributes.rb +234 -0
  35. data/lib/mongoid/attributes/processing.rb +146 -0
  36. data/lib/mongoid/callbacks.rb +135 -0
  37. data/lib/mongoid/collection.rb +153 -0
  38. data/lib/mongoid/collection_proxy.rb +59 -0
  39. data/lib/mongoid/collections.rb +120 -0
  40. data/lib/mongoid/collections/master.rb +45 -0
  41. data/lib/mongoid/collections/operations.rb +44 -0
  42. data/lib/mongoid/collections/retry.rb +46 -0
  43. data/lib/mongoid/components.rb +96 -0
  44. data/lib/mongoid/config.rb +347 -0
  45. data/lib/mongoid/config/database.rb +186 -0
  46. data/lib/mongoid/config/replset_database.rb +82 -0
  47. data/lib/mongoid/connection_proxy.rb +30 -0
  48. data/lib/mongoid/contexts.rb +25 -0
  49. data/lib/mongoid/contexts/enumerable.rb +288 -0
  50. data/lib/mongoid/contexts/enumerable/sort.rb +43 -0
  51. data/lib/mongoid/contexts/mongo.rb +409 -0
  52. data/lib/mongoid/copyable.rb +48 -0
  53. data/lib/mongoid/criteria.rb +418 -0
  54. data/lib/mongoid/criterion/builder.rb +34 -0
  55. data/lib/mongoid/criterion/complex.rb +84 -0
  56. data/lib/mongoid/criterion/creational.rb +34 -0
  57. data/lib/mongoid/criterion/exclusion.rb +108 -0
  58. data/lib/mongoid/criterion/inclusion.rb +305 -0
  59. data/lib/mongoid/criterion/inspection.rb +22 -0
  60. data/lib/mongoid/criterion/optional.rb +232 -0
  61. data/lib/mongoid/criterion/selector.rb +153 -0
  62. data/lib/mongoid/cursor.rb +86 -0
  63. data/lib/mongoid/database_proxy.rb +97 -0
  64. data/lib/mongoid/default_scope.rb +36 -0
  65. data/lib/mongoid/dirty.rb +110 -0
  66. data/lib/mongoid/document.rb +280 -0
  67. data/lib/mongoid/errors.rb +17 -0
  68. data/lib/mongoid/errors/callback.rb +26 -0
  69. data/lib/mongoid/errors/document_not_found.rb +28 -0
  70. data/lib/mongoid/errors/eager_load.rb +25 -0
  71. data/lib/mongoid/errors/invalid_collection.rb +18 -0
  72. data/lib/mongoid/errors/invalid_database.rb +19 -0
  73. data/lib/mongoid/errors/invalid_field.rb +18 -0
  74. data/lib/mongoid/errors/invalid_find.rb +19 -0
  75. data/lib/mongoid/errors/invalid_options.rb +28 -0
  76. data/lib/mongoid/errors/invalid_time.rb +25 -0
  77. data/lib/mongoid/errors/invalid_type.rb +25 -0
  78. data/lib/mongoid/errors/mixed_relations.rb +37 -0
  79. data/lib/mongoid/errors/mongoid_error.rb +26 -0
  80. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +20 -0
  81. data/lib/mongoid/errors/unsaved_document.rb +23 -0
  82. data/lib/mongoid/errors/unsupported_version.rb +20 -0
  83. data/lib/mongoid/errors/validations.rb +23 -0
  84. data/lib/mongoid/extensions.rb +82 -0
  85. data/lib/mongoid/extensions/array/deletion.rb +29 -0
  86. data/lib/mongoid/extensions/false_class/equality.rb +26 -0
  87. data/lib/mongoid/extensions/hash/criteria_helpers.rb +45 -0
  88. data/lib/mongoid/extensions/hash/scoping.rb +25 -0
  89. data/lib/mongoid/extensions/integer/checks.rb +23 -0
  90. data/lib/mongoid/extensions/nil/collectionization.rb +23 -0
  91. data/lib/mongoid/extensions/object/checks.rb +29 -0
  92. data/lib/mongoid/extensions/object/reflections.rb +48 -0
  93. data/lib/mongoid/extensions/object/substitutable.rb +15 -0
  94. data/lib/mongoid/extensions/object/yoda.rb +44 -0
  95. data/lib/mongoid/extensions/object_id/conversions.rb +60 -0
  96. data/lib/mongoid/extensions/proc/scoping.rb +25 -0
  97. data/lib/mongoid/extensions/string/checks.rb +36 -0
  98. data/lib/mongoid/extensions/string/conversions.rb +22 -0
  99. data/lib/mongoid/extensions/string/inflections.rb +118 -0
  100. data/lib/mongoid/extensions/symbol/checks.rb +23 -0
  101. data/lib/mongoid/extensions/symbol/inflections.rb +66 -0
  102. data/lib/mongoid/extensions/true_class/equality.rb +26 -0
  103. data/lib/mongoid/extras.rb +31 -0
  104. data/lib/mongoid/factory.rb +46 -0
  105. data/lib/mongoid/fields.rb +332 -0
  106. data/lib/mongoid/fields/mappings.rb +41 -0
  107. data/lib/mongoid/fields/serializable.rb +201 -0
  108. data/lib/mongoid/fields/serializable/array.rb +49 -0
  109. data/lib/mongoid/fields/serializable/big_decimal.rb +42 -0
  110. data/lib/mongoid/fields/serializable/bignum.rb +10 -0
  111. data/lib/mongoid/fields/serializable/binary.rb +11 -0
  112. data/lib/mongoid/fields/serializable/boolean.rb +43 -0
  113. data/lib/mongoid/fields/serializable/date.rb +51 -0
  114. data/lib/mongoid/fields/serializable/date_time.rb +28 -0
  115. data/lib/mongoid/fields/serializable/fixnum.rb +10 -0
  116. data/lib/mongoid/fields/serializable/float.rb +32 -0
  117. data/lib/mongoid/fields/serializable/foreign_keys/array.rb +42 -0
  118. data/lib/mongoid/fields/serializable/foreign_keys/object.rb +47 -0
  119. data/lib/mongoid/fields/serializable/hash.rb +11 -0
  120. data/lib/mongoid/fields/serializable/integer.rb +44 -0
  121. data/lib/mongoid/fields/serializable/localized.rb +41 -0
  122. data/lib/mongoid/fields/serializable/nil_class.rb +38 -0
  123. data/lib/mongoid/fields/serializable/object.rb +11 -0
  124. data/lib/mongoid/fields/serializable/object_id.rb +31 -0
  125. data/lib/mongoid/fields/serializable/range.rb +42 -0
  126. data/lib/mongoid/fields/serializable/set.rb +42 -0
  127. data/lib/mongoid/fields/serializable/string.rb +27 -0
  128. data/lib/mongoid/fields/serializable/symbol.rb +27 -0
  129. data/lib/mongoid/fields/serializable/time.rb +23 -0
  130. data/lib/mongoid/fields/serializable/time_with_zone.rb +23 -0
  131. data/lib/mongoid/fields/serializable/timekeeping.rb +106 -0
  132. data/lib/mongoid/finders.rb +152 -0
  133. data/lib/mongoid/hierarchy.rb +120 -0
  134. data/lib/mongoid/identity.rb +92 -0
  135. data/lib/mongoid/identity_map.rb +119 -0
  136. data/lib/mongoid/indexes.rb +54 -0
  137. data/lib/mongoid/inspection.rb +54 -0
  138. data/lib/mongoid/javascript.rb +20 -0
  139. data/lib/mongoid/javascript/functions.yml +63 -0
  140. data/lib/mongoid/json.rb +16 -0
  141. data/lib/mongoid/keys.rb +144 -0
  142. data/lib/mongoid/logger.rb +39 -0
  143. data/lib/mongoid/matchers.rb +32 -0
  144. data/lib/mongoid/matchers/all.rb +21 -0
  145. data/lib/mongoid/matchers/and.rb +30 -0
  146. data/lib/mongoid/matchers/default.rb +70 -0
  147. data/lib/mongoid/matchers/exists.rb +23 -0
  148. data/lib/mongoid/matchers/gt.rb +21 -0
  149. data/lib/mongoid/matchers/gte.rb +21 -0
  150. data/lib/mongoid/matchers/in.rb +21 -0
  151. data/lib/mongoid/matchers/lt.rb +21 -0
  152. data/lib/mongoid/matchers/lte.rb +21 -0
  153. data/lib/mongoid/matchers/ne.rb +21 -0
  154. data/lib/mongoid/matchers/nin.rb +21 -0
  155. data/lib/mongoid/matchers/or.rb +33 -0
  156. data/lib/mongoid/matchers/size.rb +21 -0
  157. data/lib/mongoid/matchers/strategies.rb +93 -0
  158. data/lib/mongoid/multi_database.rb +31 -0
  159. data/lib/mongoid/multi_parameter_attributes.rb +106 -0
  160. data/lib/mongoid/named_scope.rb +146 -0
  161. data/lib/mongoid/nested_attributes.rb +54 -0
  162. data/lib/mongoid/observer.rb +170 -0
  163. data/lib/mongoid/paranoia.rb +158 -0
  164. data/lib/mongoid/persistence.rb +264 -0
  165. data/lib/mongoid/persistence/atomic.rb +223 -0
  166. data/lib/mongoid/persistence/atomic/add_to_set.rb +35 -0
  167. data/lib/mongoid/persistence/atomic/bit.rb +37 -0
  168. data/lib/mongoid/persistence/atomic/inc.rb +31 -0
  169. data/lib/mongoid/persistence/atomic/operation.rb +85 -0
  170. data/lib/mongoid/persistence/atomic/pop.rb +34 -0
  171. data/lib/mongoid/persistence/atomic/pull.rb +34 -0
  172. data/lib/mongoid/persistence/atomic/pull_all.rb +34 -0
  173. data/lib/mongoid/persistence/atomic/push.rb +31 -0
  174. data/lib/mongoid/persistence/atomic/push_all.rb +31 -0
  175. data/lib/mongoid/persistence/atomic/rename.rb +31 -0
  176. data/lib/mongoid/persistence/atomic/sets.rb +30 -0
  177. data/lib/mongoid/persistence/atomic/unset.rb +28 -0
  178. data/lib/mongoid/persistence/deletion.rb +32 -0
  179. data/lib/mongoid/persistence/insertion.rb +41 -0
  180. data/lib/mongoid/persistence/modification.rb +37 -0
  181. data/lib/mongoid/persistence/operations.rb +211 -0
  182. data/lib/mongoid/persistence/operations/embedded/insert.rb +42 -0
  183. data/lib/mongoid/persistence/operations/embedded/remove.rb +40 -0
  184. data/lib/mongoid/persistence/operations/insert.rb +34 -0
  185. data/lib/mongoid/persistence/operations/remove.rb +33 -0
  186. data/lib/mongoid/persistence/operations/update.rb +64 -0
  187. data/lib/mongoid/railtie.rb +126 -0
  188. data/lib/mongoid/railties/database.rake +182 -0
  189. data/lib/mongoid/railties/document.rb +12 -0
  190. data/lib/mongoid/relations.rb +144 -0
  191. data/lib/mongoid/relations/accessors.rb +138 -0
  192. data/lib/mongoid/relations/auto_save.rb +38 -0
  193. data/lib/mongoid/relations/binding.rb +26 -0
  194. data/lib/mongoid/relations/bindings.rb +9 -0
  195. data/lib/mongoid/relations/bindings/embedded/in.rb +69 -0
  196. data/lib/mongoid/relations/bindings/embedded/many.rb +93 -0
  197. data/lib/mongoid/relations/bindings/embedded/one.rb +61 -0
  198. data/lib/mongoid/relations/bindings/referenced/in.rb +76 -0
  199. data/lib/mongoid/relations/bindings/referenced/many.rb +54 -0
  200. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +51 -0
  201. data/lib/mongoid/relations/bindings/referenced/one.rb +58 -0
  202. data/lib/mongoid/relations/builder.rb +57 -0
  203. data/lib/mongoid/relations/builders.rb +83 -0
  204. data/lib/mongoid/relations/builders/embedded/in.rb +29 -0
  205. data/lib/mongoid/relations/builders/embedded/many.rb +40 -0
  206. data/lib/mongoid/relations/builders/embedded/one.rb +30 -0
  207. data/lib/mongoid/relations/builders/nested_attributes/many.rb +110 -0
  208. data/lib/mongoid/relations/builders/nested_attributes/one.rb +135 -0
  209. data/lib/mongoid/relations/builders/referenced/in.rb +26 -0
  210. data/lib/mongoid/relations/builders/referenced/many.rb +27 -0
  211. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +38 -0
  212. data/lib/mongoid/relations/builders/referenced/one.rb +26 -0
  213. data/lib/mongoid/relations/cascading.rb +56 -0
  214. data/lib/mongoid/relations/cascading/delete.rb +19 -0
  215. data/lib/mongoid/relations/cascading/destroy.rb +26 -0
  216. data/lib/mongoid/relations/cascading/nullify.rb +18 -0
  217. data/lib/mongoid/relations/cascading/strategy.rb +26 -0
  218. data/lib/mongoid/relations/constraint.rb +42 -0
  219. data/lib/mongoid/relations/conversions.rb +35 -0
  220. data/lib/mongoid/relations/cyclic.rb +103 -0
  221. data/lib/mongoid/relations/embedded/atomic.rb +89 -0
  222. data/lib/mongoid/relations/embedded/atomic/operation.rb +63 -0
  223. data/lib/mongoid/relations/embedded/atomic/pull.rb +65 -0
  224. data/lib/mongoid/relations/embedded/atomic/push_all.rb +59 -0
  225. data/lib/mongoid/relations/embedded/atomic/set.rb +61 -0
  226. data/lib/mongoid/relations/embedded/atomic/unset.rb +41 -0
  227. data/lib/mongoid/relations/embedded/in.rb +220 -0
  228. data/lib/mongoid/relations/embedded/many.rb +560 -0
  229. data/lib/mongoid/relations/embedded/one.rb +206 -0
  230. data/lib/mongoid/relations/embedded/sort.rb +31 -0
  231. data/lib/mongoid/relations/macros.rb +310 -0
  232. data/lib/mongoid/relations/many.rb +135 -0
  233. data/lib/mongoid/relations/metadata.rb +919 -0
  234. data/lib/mongoid/relations/nested_builder.rb +75 -0
  235. data/lib/mongoid/relations/one.rb +36 -0
  236. data/lib/mongoid/relations/options.rb +47 -0
  237. data/lib/mongoid/relations/polymorphic.rb +40 -0
  238. data/lib/mongoid/relations/proxy.rb +145 -0
  239. data/lib/mongoid/relations/referenced/batch.rb +72 -0
  240. data/lib/mongoid/relations/referenced/batch/insert.rb +57 -0
  241. data/lib/mongoid/relations/referenced/in.rb +262 -0
  242. data/lib/mongoid/relations/referenced/many.rb +623 -0
  243. data/lib/mongoid/relations/referenced/many_to_many.rb +396 -0
  244. data/lib/mongoid/relations/referenced/one.rb +272 -0
  245. data/lib/mongoid/relations/reflections.rb +62 -0
  246. data/lib/mongoid/relations/synchronization.rb +153 -0
  247. data/lib/mongoid/relations/targets.rb +2 -0
  248. data/lib/mongoid/relations/targets/enumerable.rb +372 -0
  249. data/lib/mongoid/reloading.rb +91 -0
  250. data/lib/mongoid/safety.rb +105 -0
  251. data/lib/mongoid/scope.rb +31 -0
  252. data/lib/mongoid/serialization.rb +134 -0
  253. data/lib/mongoid/sharding.rb +61 -0
  254. data/lib/mongoid/state.rb +97 -0
  255. data/lib/mongoid/threaded.rb +530 -0
  256. data/lib/mongoid/threaded/lifecycle.rb +192 -0
  257. data/lib/mongoid/timestamps.rb +15 -0
  258. data/lib/mongoid/timestamps/created.rb +24 -0
  259. data/lib/mongoid/timestamps/timeless.rb +50 -0
  260. data/lib/mongoid/timestamps/updated.rb +26 -0
  261. data/lib/mongoid/validations.rb +140 -0
  262. data/lib/mongoid/validations/associated.rb +46 -0
  263. data/lib/mongoid/validations/uniqueness.rb +145 -0
  264. data/lib/mongoid/version.rb +4 -0
  265. data/lib/mongoid/versioning.rb +185 -0
  266. data/lib/rack/mongoid.rb +2 -0
  267. data/lib/rack/mongoid/middleware/identity_map.rb +38 -0
  268. data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
  269. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +20 -0
  270. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  271. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +19 -0
  272. data/lib/rails/generators/mongoid/observer/observer_generator.rb +17 -0
  273. data/lib/rails/generators/mongoid/observer/templates/observer.rb.tt +4 -0
  274. data/lib/rails/generators/mongoid_generator.rb +70 -0
  275. data/lib/rails/mongoid.rb +91 -0
  276. metadata +465 -0
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Criterion #:nodoc:
4
+ module Inspection #:nodoc:
5
+
6
+ # Get a pretty string representation of the criteria, including the
7
+ # selector, options, matching count and documents for inspection.
8
+ #
9
+ # @example Inspect the criteria.
10
+ # criteria.inspect
11
+ #
12
+ # @return [ String ] The inspection string.
13
+ def inspect
14
+ "#<Mongoid::Criteria\n" <<
15
+ " selector: #{selector.inspect},\n" <<
16
+ " options: #{options.inspect},\n" <<
17
+ " class: #{klass},\n" <<
18
+ " embedded: #{embedded}>\n"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,232 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Criterion #:nodoc:
4
+ module Optional
5
+
6
+ # Adds fields to be sorted in ascending order. Will add them in the order
7
+ # they were passed into the method.
8
+ #
9
+ # @example Sort in ascending order.
10
+ # criteria.ascending(:title, :dob)
11
+ # criteria.asc(:title, :dob)
12
+ #
13
+ # @param [ Array<Symbol> ] fields The fields to sort on.
14
+ #
15
+ # @return [ Criteria ] The cloned criteria.
16
+ def ascending(*fields)
17
+ clone.tap do |crit|
18
+ crit.options[:sort] = [] unless options[:sort] || fields.first.nil?
19
+ fields.flatten.each { |field| merge_options(crit.options[:sort], [ field, :asc ]) }
20
+ end
21
+ end
22
+ alias :asc :ascending
23
+
24
+ # Tells the criteria that the cursor that gets returned needs to be
25
+ # cached. This is so multiple iterations don't hit the database multiple
26
+ # times, however this is not advisable when working with large data sets
27
+ # as the entire results will get stored in memory.
28
+ #
29
+ # @example Flag the criteria as cached.
30
+ # criteria.cache
31
+ #
32
+ # @return [ Criteria ] The cloned criteria.
33
+ def cache
34
+ clone.tap { |crit| crit.options.merge!(:cache => true) }
35
+ end
36
+
37
+ # Will return true if the cache option has been set.
38
+ #
39
+ # @example Is the criteria cached?
40
+ # criteria.cached?
41
+ #
42
+ # @return [ true, false ] If the criteria is flagged as cached.
43
+ def cached?
44
+ options[:cache] == true
45
+ end
46
+
47
+ # Adds fields to be sorted in descending order. Will add them in the order
48
+ # they were passed into the method.
49
+ #
50
+ # @example Sort the criteria in descending order.
51
+ # criteria.descending(:title, :dob)
52
+ # criteria.desc(:title, :dob)
53
+ #
54
+ # @param [ Array<Symbol> ] fields The fields to sort on.
55
+ #
56
+ # @return [ Criteria ] The cloned criteria.
57
+ def descending(*fields)
58
+ clone.tap do |crit|
59
+ crit.options[:sort] = [] unless options[:sort] || fields.first.nil?
60
+ fields.flatten.each { |field| merge_options(crit.options[:sort], [ field, :desc ]) }
61
+ end
62
+ end
63
+ alias :desc :descending
64
+
65
+ # Adds a criterion to the +Criteria+ that specifies additional options
66
+ # to be passed to the Ruby driver, in the exact format for the driver.
67
+ #
68
+ # @example Add extra params to the criteria.
69
+ # criteria.extras(:limit => 20, :skip => 40)
70
+ #
71
+ # @param [ Hash ] extras The extra driver options.
72
+ #
73
+ # @return [ Criteria ] The cloned criteria.
74
+ def extras(extras)
75
+ clone.tap do |crit|
76
+ crit.options.merge!(extras)
77
+ end
78
+ end
79
+
80
+ # Adds a criterion to the +Criteria+ that specifies an id that must be matched.
81
+ #
82
+ # @example Add a single id criteria.
83
+ # criteria.for_ids("4ab2bc4b8ad548971900005c")
84
+ #
85
+ # @example Add multiple id criteria.
86
+ # criteria.for_ids(["4ab2bc4b8ad548971900005c", "4c454e7ebf4b98032d000001"])
87
+ #
88
+ # @param [ Array ] ids: A single id or an array of ids.
89
+ #
90
+ # @return [ Criteria ] The cloned criteria.
91
+ def for_ids(*ids)
92
+ ids.flatten!
93
+ if ids.size > 1
94
+ where(:_id.in => ::BSON::ObjectId.convert(klass, ids))
95
+ else
96
+ where(:_id => ids.first)
97
+ end
98
+ end
99
+
100
+ # Adds a criterion to the +Criteria+ that specifies the maximum number of
101
+ # results to return. This is mostly used in conjunction with skip()
102
+ # to handle paginated results.
103
+ #
104
+ # @example Limit the result set size.
105
+ # criteria.limit(100)
106
+ #
107
+ # @param [ Integer ] value The max number of results.
108
+ #
109
+ # @return [ Criteria ] The cloned criteria.
110
+ def limit(value = 20)
111
+ clone.tap { |crit| crit.options[:limit] = value }
112
+ end
113
+
114
+ # Returns the offset option. If a per_page option is in the list then it
115
+ # will replace it with a skip parameter and return the same value. Defaults
116
+ # to 20 if nothing was provided.
117
+ #
118
+ # @example Get the offset.
119
+ # criteria.offset(10)
120
+ #
121
+ # @return [ Integer ] The number of documents to skip.
122
+ def offset(*args)
123
+ args.size > 0 ? skip(args.first) : options[:skip]
124
+ end
125
+
126
+ # Adds a criterion to the +Criteria+ that specifies the sort order of
127
+ # the returned documents in the database. Similar to a SQL "ORDER BY".
128
+ #
129
+ # @example Order by specific fields.
130
+ # criteria.order_by([[:field1, :asc], [:field2, :desc]])
131
+ #
132
+ # @param [ Array ] params: An +Array+ of [field, direction] sorting pairs.
133
+ #
134
+ # @return [ Criteria ] The cloned criteria.
135
+ def order_by(*args)
136
+ clone.tap do |crit|
137
+ arguments = args.size == 1 ? args.first : args
138
+ crit.options[:sort] = [] unless options[:sort] || args.first.nil?
139
+ if arguments.is_a?(Array)
140
+ #[:name, :asc]
141
+ if arguments.size == 2 && (arguments.first.is_a?(Symbol) || arguments.first.is_a?(String))
142
+ build_order_options(arguments, crit)
143
+ else
144
+ arguments.each { |argument| build_order_options(argument, crit) }
145
+ end
146
+ else
147
+ build_order_options(arguments, crit)
148
+ end
149
+ end
150
+ end
151
+ alias :order :order_by
152
+
153
+ # Adds a criterion to the +Criteria+ that specifies how many results to skip
154
+ # when returning Documents. This is mostly used in conjunction with
155
+ # limit() to handle paginated results, and is similar to the
156
+ # traditional "offset" parameter.
157
+ #
158
+ # @example Skip a specified number of documents.
159
+ # criteria.skip(20)
160
+ #
161
+ # @param [ Integer ] value The number of results to skip.
162
+ #
163
+ # @return [ Criteria ] The cloned criteria.
164
+ def skip(value = 0)
165
+ clone.tap { |crit| crit.options[:skip] = value }
166
+ end
167
+
168
+ # Adds a criterion to the +Criteria+ that specifies a type or an Array of
169
+ # types that must be matched.
170
+ #
171
+ # @example Match only specific models.
172
+ # criteria.type('Browser')
173
+ # criteria.type(['Firefox', 'Browser'])
174
+ #
175
+ # @param [ Array<String> ] types The types to match against.
176
+ #
177
+ # @return [ Criteria ] The cloned criteria.
178
+ def type(types)
179
+ types = [types] unless types.is_a?(Array)
180
+ any_in(:_type => types)
181
+ end
182
+
183
+ private
184
+
185
+ # Build ordering options from given arguments on given criteria
186
+ #
187
+ # @example build order options
188
+ # criteria.build_order_options(:name.asc, criteria)
189
+ #
190
+ #
191
+ # @param [ <Hash>, <Array>, <Complex> ] argument to build criteria from
192
+ # @param [ Criterion ] criterion to change
193
+ def build_order_options(arguments, crit)
194
+ case arguments
195
+ when Hash
196
+ if arguments.size > 1
197
+ raise ArgumentError, "Please don't use hash to define multiple orders " +
198
+ "due to the fact that hash doesn't have order this may cause unpredictable results"
199
+ end
200
+ arguments.each_pair do |field, direction|
201
+ merge_options(crit.options[:sort], [ field, direction ])
202
+ end
203
+ when Array
204
+ merge_options(crit.options[:sort],arguments)
205
+ when Complex
206
+ merge_options(crit.options[:sort], [ arguments.key, arguments.operator.to_sym ])
207
+ end
208
+ end
209
+
210
+ # Merge options for order_by criterion
211
+ # Allow only one order direction for same field
212
+ #
213
+ # @example Merge ordering options
214
+ # criteria.merge_options([[:title, :asc], [:created_at, :asc]], [:title, :desc])
215
+ #
216
+ #
217
+ # @param [ Array<Array> ] Existing options
218
+ # @param [ Array ] New option for merge.
219
+ #
220
+ # @since 2.1.0
221
+ def merge_options(options, new_option)
222
+ old_option = options.assoc(new_option.first)
223
+
224
+ if old_option
225
+ options[options.index(old_option)] = new_option.flatten
226
+ else
227
+ options << new_option.flatten
228
+ end
229
+ end
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,153 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Criterion #:nodoc:
4
+
5
+ # The selector is a hash-like object that has special behaviour for merging
6
+ # mongoid criteria selectors.
7
+ class Selector < Hash
8
+
9
+ attr_reader :fields, :klass
10
+
11
+ # Create the new selector.
12
+ #
13
+ # @example Create the selector.
14
+ # Selector.new(Person)
15
+ #
16
+ # @param [ Class ] klass The class the selector is for.
17
+ #
18
+ # @since 1.0.0
19
+ def initialize(klass)
20
+ @fields, @klass = klass.fields.except("_id", "_type"), klass
21
+ end
22
+
23
+ # Set the value for the supplied key, attempting to typecast the value.
24
+ #
25
+ # @example Set the value for the key.
26
+ # selector["$ne"] = { :name => "Zorg" }
27
+ #
28
+ # @param [ String, Symbol ] key The hash key.
29
+ # @param [ Object ] value The value to set.
30
+ #
31
+ # @since 2.0.0
32
+ def []=(key, value)
33
+ key = "#{key}.#{::I18n.locale}" if klass.fields[key.to_s].try(:localized?)
34
+ super(key, try_to_typecast(key, value))
35
+ end
36
+
37
+ # Merge the selector with another hash.
38
+ #
39
+ # @example Merge the objects.
40
+ # selector.merge!({ :key => "value" })
41
+ #
42
+ # @param [ Hash, Selector ] other The object to merge with.
43
+ #
44
+ # @return [ Selector ] The merged selector.
45
+ #
46
+ # @since 1.0.0
47
+ def merge!(other)
48
+ tap do |selector|
49
+ other.each_pair do |key, value|
50
+ selector[key] = value
51
+ end
52
+ end
53
+ end
54
+ alias :update :merge!
55
+
56
+ if RUBY_VERSION < '1.9'
57
+
58
+ # Generate pretty inspection for old ruby versions.
59
+ #
60
+ # @example Inspect the selector.
61
+ # selector.inspect
62
+ #
63
+ # @return [ String ] The inspected selector.
64
+ def inspect
65
+ ret = self.keys.inject([]) do |ret, key|
66
+ ret << "#{key.inspect}=>#{self[key].inspect}"
67
+ end
68
+ "{#{ret.sort.join(', ')}}"
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ # If the key is defined as a field, then attempt to typecast it.
75
+ #
76
+ # @example Try to cast.
77
+ # selector.try_to_typecast(:id, 1)
78
+ #
79
+ # @param [ String, Symbol ] key The field name.
80
+ # @param [ Object ] value The value.
81
+ #
82
+ # @return [ Object ] The typecasted value.
83
+ #
84
+ # @since 1.0.0
85
+ def try_to_typecast(key, value)
86
+ access = key.to_s
87
+ return value unless fields.has_key?(access)
88
+ field = fields[access]
89
+ typecast_value_for(field, value)
90
+ end
91
+
92
+ # Get the typecast value for the defined field.
93
+ #
94
+ # @example Get the typecast value.
95
+ # selector.typecast_value_for(:name, "Corbin")
96
+ #
97
+ # @param [ Field ] field The defined field.
98
+ # @param [ Object ] value The value to cast.
99
+ #
100
+ # @return [ Object ] The cast value.
101
+ #
102
+ # @since 1.0.0
103
+ def typecast_value_for(field, value)
104
+ return field.serialize(value) if field.type === value
105
+ case value
106
+ when Hash
107
+ value = value.dup
108
+ value.each_pair do |k, v|
109
+ value[k] = typecast_hash_value(field, k, v)
110
+ end
111
+ when Array
112
+ value.map { |v| typecast_value_for(field, v) }
113
+ when Regexp
114
+ value
115
+ when Range
116
+ {
117
+ "$gte" => typecast_value_for(field, value.first),
118
+ "$lte" => typecast_value_for(field, value.last)
119
+ }
120
+ else
121
+ if field.type == Array
122
+ Serialization.mongoize(value, value.class)
123
+ else
124
+ field.serialize(value)
125
+ end
126
+ end
127
+ end
128
+
129
+ # Typecast the value for booleans and integers in hashes.
130
+ #
131
+ # @example Typecast the hash values.
132
+ # selector.typecast_hash_value(field, "$exists", "true")
133
+ #
134
+ # @param [ Field ] field The defined field.
135
+ # @param [ String ] key The modifier key.
136
+ # @param [ Object ] value The value to cast.
137
+ #
138
+ # @return [ Object ] The cast value.
139
+ #
140
+ # @since 1.0.0
141
+ def typecast_hash_value(field, key, value)
142
+ case key
143
+ when "$exists"
144
+ Serialization.mongoize(value, Boolean)
145
+ when "$size"
146
+ Serialization.mongoize(value, Integer)
147
+ else
148
+ typecast_value_for(field, value)
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,86 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc
3
+
4
+ # Mongoid wrapper of the Ruby Driver cursor.
5
+ class Cursor
6
+ include Mongoid::Collections::Retry
7
+ include Enumerable
8
+
9
+ # Operations on the Mongo::Cursor object that will not get overriden by the
10
+ # Mongoid::Cursor are defined here.
11
+ OPERATIONS = [
12
+ :close,
13
+ :closed?,
14
+ :count,
15
+ :explain,
16
+ :fields,
17
+ :full_collection_name,
18
+ :hint,
19
+ :limit,
20
+ :order,
21
+ :query_options_hash,
22
+ :query_opts,
23
+ :selector,
24
+ :skip,
25
+ :snapshot,
26
+ :sort,
27
+ :timeout
28
+ ]
29
+
30
+ attr_reader :collection, :cursor, :klass
31
+
32
+ # The operations above will all delegate to the proxied Mongo::Cursor.
33
+ OPERATIONS.each do |name|
34
+ class_eval <<-EOS, __FILE__, __LINE__
35
+ def #{name}(*args)
36
+ retry_on_connection_failure do
37
+ cursor.#{name}(*args)
38
+ end
39
+ end
40
+ EOS
41
+ end
42
+
43
+ # Iterate over each document in the cursor and yield to it.
44
+ #
45
+ # @example Iterate over the cursor.
46
+ # cursor.each { |doc| p doc.title }
47
+ def each
48
+ cursor.each do |document|
49
+ yield Mongoid::Factory.from_db(klass, document)
50
+ end
51
+ end
52
+
53
+ # Create the new +Mongoid::Cursor+.
54
+ #
55
+ # @example Instantiate the cursor.
56
+ # Mongoid::Cursor.new(Person, cursor)
57
+ #
58
+ # @param [ Class ] klass The class associated with the cursor.
59
+ # @param [ Collection ] collection The Mongoid::Collection instance.
60
+ # @param [ Mongo::Cursor ] cursor The Mongo::Cursor to be proxied.
61
+ def initialize(klass, collection, cursor)
62
+ @klass, @collection, @cursor = klass, collection, cursor
63
+ end
64
+
65
+ # Return the next document in the cursor. Will instantiate a new Mongoid
66
+ # document with the attributes.
67
+ #
68
+ # @example Get the next document.
69
+ # cursor.next_document
70
+ #
71
+ # @return [ Document ] The next document in the cursor.
72
+ def next_document
73
+ Mongoid::Factory.from_db(klass, cursor.next_document)
74
+ end
75
+
76
+ # Returns an array of all the documents in the cursor.
77
+ #
78
+ # @example Get the cursor as an array.
79
+ # cursor.to_a
80
+ #
81
+ # @return [ Array<Document> ] An array of documents.
82
+ def to_a
83
+ cursor.to_a.collect { |attrs| Mongoid::Factory.from_db(klass, attrs) }
84
+ end
85
+ end
86
+ end