mongoid-locomotive 2.0.0.beta9

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 (274) hide show
  1. data/MIT_LICENSE +20 -0
  2. data/README.rdoc +47 -0
  3. data/lib/mongoid.rb +141 -0
  4. data/lib/mongoid/associations.rb +306 -0
  5. data/lib/mongoid/associations/embedded_in.rb +74 -0
  6. data/lib/mongoid/associations/embeds_many.rb +280 -0
  7. data/lib/mongoid/associations/embeds_one.rb +97 -0
  8. data/lib/mongoid/associations/foreign_key.rb +35 -0
  9. data/lib/mongoid/associations/meta_data.rb +38 -0
  10. data/lib/mongoid/associations/options.rb +62 -0
  11. data/lib/mongoid/associations/proxy.rb +33 -0
  12. data/lib/mongoid/associations/referenced_in.rb +59 -0
  13. data/lib/mongoid/associations/references_many.rb +245 -0
  14. data/lib/mongoid/associations/references_many_as_array.rb +78 -0
  15. data/lib/mongoid/associations/references_one.rb +99 -0
  16. data/lib/mongoid/atomicity.rb +55 -0
  17. data/lib/mongoid/attributes.rb +242 -0
  18. data/lib/mongoid/callbacks.rb +21 -0
  19. data/lib/mongoid/collection.rb +120 -0
  20. data/lib/mongoid/collections.rb +71 -0
  21. data/lib/mongoid/collections/cyclic_iterator.rb +34 -0
  22. data/lib/mongoid/collections/master.rb +29 -0
  23. data/lib/mongoid/collections/operations.rb +41 -0
  24. data/lib/mongoid/collections/slaves.rb +45 -0
  25. data/lib/mongoid/components.rb +34 -0
  26. data/lib/mongoid/config.rb +263 -0
  27. data/lib/mongoid/contexts.rb +24 -0
  28. data/lib/mongoid/contexts/enumerable.rb +156 -0
  29. data/lib/mongoid/contexts/ids.rb +25 -0
  30. data/lib/mongoid/contexts/mongo.rb +285 -0
  31. data/lib/mongoid/contexts/paging.rb +50 -0
  32. data/lib/mongoid/criteria.rb +248 -0
  33. data/lib/mongoid/criterion/complex.rb +21 -0
  34. data/lib/mongoid/criterion/exclusion.rb +65 -0
  35. data/lib/mongoid/criterion/inclusion.rb +110 -0
  36. data/lib/mongoid/criterion/optional.rb +189 -0
  37. data/lib/mongoid/cursor.rb +81 -0
  38. data/lib/mongoid/deprecation.rb +21 -0
  39. data/lib/mongoid/dirty.rb +252 -0
  40. data/lib/mongoid/document.rb +210 -0
  41. data/lib/mongoid/errors.rb +131 -0
  42. data/lib/mongoid/extensions.rb +115 -0
  43. data/lib/mongoid/extensions/array/accessors.rb +17 -0
  44. data/lib/mongoid/extensions/array/assimilation.rb +26 -0
  45. data/lib/mongoid/extensions/array/conversions.rb +23 -0
  46. data/lib/mongoid/extensions/array/parentization.rb +13 -0
  47. data/lib/mongoid/extensions/big_decimal/conversions.rb +19 -0
  48. data/lib/mongoid/extensions/binary/conversions.rb +17 -0
  49. data/lib/mongoid/extensions/boolean/conversions.rb +27 -0
  50. data/lib/mongoid/extensions/date/conversions.rb +24 -0
  51. data/lib/mongoid/extensions/datetime/conversions.rb +12 -0
  52. data/lib/mongoid/extensions/false_class/equality.rb +13 -0
  53. data/lib/mongoid/extensions/float/conversions.rb +20 -0
  54. data/lib/mongoid/extensions/hash/accessors.rb +42 -0
  55. data/lib/mongoid/extensions/hash/assimilation.rb +40 -0
  56. data/lib/mongoid/extensions/hash/conversions.rb +42 -0
  57. data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
  58. data/lib/mongoid/extensions/hash/scoping.rb +12 -0
  59. data/lib/mongoid/extensions/integer/conversions.rb +20 -0
  60. data/lib/mongoid/extensions/nil/assimilation.rb +17 -0
  61. data/lib/mongoid/extensions/object/conversions.rb +21 -0
  62. data/lib/mongoid/extensions/objectid/conversions.rb +15 -0
  63. data/lib/mongoid/extensions/proc/scoping.rb +12 -0
  64. data/lib/mongoid/extensions/set/conversions.rb +20 -0
  65. data/lib/mongoid/extensions/string/conversions.rb +15 -0
  66. data/lib/mongoid/extensions/string/inflections.rb +97 -0
  67. data/lib/mongoid/extensions/symbol/inflections.rb +40 -0
  68. data/lib/mongoid/extensions/time_conversions.rb +35 -0
  69. data/lib/mongoid/extensions/true_class/equality.rb +13 -0
  70. data/lib/mongoid/extras.rb +61 -0
  71. data/lib/mongoid/factory.rb +20 -0
  72. data/lib/mongoid/field.rb +83 -0
  73. data/lib/mongoid/fields.rb +62 -0
  74. data/lib/mongoid/finders.rb +145 -0
  75. data/lib/mongoid/hierarchy.rb +74 -0
  76. data/lib/mongoid/identity.rb +47 -0
  77. data/lib/mongoid/indexes.rb +27 -0
  78. data/lib/mongoid/javascript.rb +21 -0
  79. data/lib/mongoid/javascript/functions.yml +37 -0
  80. data/lib/mongoid/logger.rb +19 -0
  81. data/lib/mongoid/matchers.rb +35 -0
  82. data/lib/mongoid/matchers/all.rb +11 -0
  83. data/lib/mongoid/matchers/default.rb +26 -0
  84. data/lib/mongoid/matchers/exists.rb +13 -0
  85. data/lib/mongoid/matchers/gt.rb +11 -0
  86. data/lib/mongoid/matchers/gte.rb +11 -0
  87. data/lib/mongoid/matchers/in.rb +11 -0
  88. data/lib/mongoid/matchers/lt.rb +11 -0
  89. data/lib/mongoid/matchers/lte.rb +11 -0
  90. data/lib/mongoid/matchers/ne.rb +11 -0
  91. data/lib/mongoid/matchers/nin.rb +11 -0
  92. data/lib/mongoid/matchers/size.rb +11 -0
  93. data/lib/mongoid/memoization.rb +33 -0
  94. data/lib/mongoid/named_scope.rb +37 -0
  95. data/lib/mongoid/paranoia.rb +106 -0
  96. data/lib/mongoid/paths.rb +61 -0
  97. data/lib/mongoid/persistence.rb +216 -0
  98. data/lib/mongoid/persistence/command.rb +39 -0
  99. data/lib/mongoid/persistence/insert.rb +48 -0
  100. data/lib/mongoid/persistence/insert_embedded.rb +44 -0
  101. data/lib/mongoid/persistence/remove.rb +39 -0
  102. data/lib/mongoid/persistence/remove_all.rb +38 -0
  103. data/lib/mongoid/persistence/remove_embedded.rb +50 -0
  104. data/lib/mongoid/persistence/update.rb +71 -0
  105. data/lib/mongoid/railtie.rb +67 -0
  106. data/lib/mongoid/railties/database.rake +60 -0
  107. data/lib/mongoid/scope.rb +75 -0
  108. data/lib/mongoid/state.rb +32 -0
  109. data/lib/mongoid/timestamps.rb +27 -0
  110. data/lib/mongoid/validations.rb +51 -0
  111. data/lib/mongoid/validations/associated.rb +32 -0
  112. data/lib/mongoid/validations/locale/en.yml +5 -0
  113. data/lib/mongoid/validations/uniqueness.rb +56 -0
  114. data/lib/mongoid/version.rb +4 -0
  115. data/lib/mongoid/versioning.rb +26 -0
  116. data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
  117. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +24 -0
  118. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  119. data/lib/rails/generators/mongoid/model/templates/model.rb +15 -0
  120. data/lib/rails/generators/mongoid_generator.rb +61 -0
  121. data/spec/integration/mongoid/association_attributes_spec.rb +71 -0
  122. data/spec/integration/mongoid/associations_spec.rb +768 -0
  123. data/spec/integration/mongoid/attributes_spec.rb +59 -0
  124. data/spec/integration/mongoid/callback_spec.rb +33 -0
  125. data/spec/integration/mongoid/contexts/enumerable_spec.rb +33 -0
  126. data/spec/integration/mongoid/criteria_spec.rb +281 -0
  127. data/spec/integration/mongoid/dirty_spec.rb +85 -0
  128. data/spec/integration/mongoid/document_spec.rb +741 -0
  129. data/spec/integration/mongoid/extensions_spec.rb +22 -0
  130. data/spec/integration/mongoid/finders_spec.rb +119 -0
  131. data/spec/integration/mongoid/inheritance_spec.rb +171 -0
  132. data/spec/integration/mongoid/named_scope_spec.rb +58 -0
  133. data/spec/integration/mongoid/paranoia_spec.rb +44 -0
  134. data/spec/integration/mongoid/persistence/update_spec.rb +46 -0
  135. data/spec/integration/mongoid/persistence_spec.rb +311 -0
  136. data/spec/integration/mongoid/validations/uniqueness_spec.rb +206 -0
  137. data/spec/models/account.rb +5 -0
  138. data/spec/models/address.rb +40 -0
  139. data/spec/models/agent.rb +7 -0
  140. data/spec/models/animal.rb +15 -0
  141. data/spec/models/answer.rb +4 -0
  142. data/spec/models/callbacks.rb +47 -0
  143. data/spec/models/category.rb +13 -0
  144. data/spec/models/comment.rb +10 -0
  145. data/spec/models/country_code.rb +6 -0
  146. data/spec/models/employer.rb +5 -0
  147. data/spec/models/favorite.rb +8 -0
  148. data/spec/models/game.rb +9 -0
  149. data/spec/models/inheritance.rb +72 -0
  150. data/spec/models/location.rb +5 -0
  151. data/spec/models/login.rb +6 -0
  152. data/spec/models/mixed_drink.rb +4 -0
  153. data/spec/models/name.rb +13 -0
  154. data/spec/models/namespacing.rb +11 -0
  155. data/spec/models/paranoid_post.rb +18 -0
  156. data/spec/models/parents.rb +32 -0
  157. data/spec/models/patient.rb +15 -0
  158. data/spec/models/person.rb +106 -0
  159. data/spec/models/pet.rb +7 -0
  160. data/spec/models/pet_owner.rb +6 -0
  161. data/spec/models/phone.rb +7 -0
  162. data/spec/models/post.rb +25 -0
  163. data/spec/models/preference.rb +7 -0
  164. data/spec/models/question.rb +8 -0
  165. data/spec/models/survey.rb +6 -0
  166. data/spec/models/translation.rb +5 -0
  167. data/spec/models/user.rb +6 -0
  168. data/spec/models/user_accout.rb +5 -0
  169. data/spec/models/vet_visit.rb +5 -0
  170. data/spec/models/video.rb +5 -0
  171. data/spec/spec_helper.rb +33 -0
  172. data/spec/unit/mongoid/associations/embedded_in_spec.rb +193 -0
  173. data/spec/unit/mongoid/associations/embeds_many_spec.rb +626 -0
  174. data/spec/unit/mongoid/associations/embeds_one_spec.rb +287 -0
  175. data/spec/unit/mongoid/associations/foreign_key_spec.rb +90 -0
  176. data/spec/unit/mongoid/associations/meta_data_spec.rb +110 -0
  177. data/spec/unit/mongoid/associations/options_spec.rb +215 -0
  178. data/spec/unit/mongoid/associations/referenced_in_spec.rb +145 -0
  179. data/spec/unit/mongoid/associations/references_many_as_array_spec.rb +424 -0
  180. data/spec/unit/mongoid/associations/references_many_spec.rb +502 -0
  181. data/spec/unit/mongoid/associations/references_one_spec.rb +204 -0
  182. data/spec/unit/mongoid/associations_spec.rb +688 -0
  183. data/spec/unit/mongoid/atomicity_spec.rb +164 -0
  184. data/spec/unit/mongoid/attributes_spec.rb +646 -0
  185. data/spec/unit/mongoid/callbacks_spec.rb +85 -0
  186. data/spec/unit/mongoid/collection_spec.rb +187 -0
  187. data/spec/unit/mongoid/collections/cyclic_iterator_spec.rb +75 -0
  188. data/spec/unit/mongoid/collections/master_spec.rb +41 -0
  189. data/spec/unit/mongoid/collections/slaves_spec.rb +81 -0
  190. data/spec/unit/mongoid/collections_spec.rb +98 -0
  191. data/spec/unit/mongoid/config_spec.rb +298 -0
  192. data/spec/unit/mongoid/contexts/enumerable_spec.rb +447 -0
  193. data/spec/unit/mongoid/contexts/mongo_spec.rb +703 -0
  194. data/spec/unit/mongoid/contexts_spec.rb +25 -0
  195. data/spec/unit/mongoid/criteria_spec.rb +873 -0
  196. data/spec/unit/mongoid/criterion/complex_spec.rb +17 -0
  197. data/spec/unit/mongoid/criterion/exclusion_spec.rb +121 -0
  198. data/spec/unit/mongoid/criterion/inclusion_spec.rb +274 -0
  199. data/spec/unit/mongoid/criterion/optional_spec.rb +483 -0
  200. data/spec/unit/mongoid/cursor_spec.rb +80 -0
  201. data/spec/unit/mongoid/deprecation_spec.rb +24 -0
  202. data/spec/unit/mongoid/dirty_spec.rb +430 -0
  203. data/spec/unit/mongoid/document_spec.rb +623 -0
  204. data/spec/unit/mongoid/errors_spec.rb +154 -0
  205. data/spec/unit/mongoid/extensions/array/accessors_spec.rb +50 -0
  206. data/spec/unit/mongoid/extensions/array/assimilation_spec.rb +24 -0
  207. data/spec/unit/mongoid/extensions/array/conversions_spec.rb +52 -0
  208. data/spec/unit/mongoid/extensions/array/parentization_spec.rb +20 -0
  209. data/spec/unit/mongoid/extensions/big_decimal/conversions_spec.rb +36 -0
  210. data/spec/unit/mongoid/extensions/binary/conversions_spec.rb +22 -0
  211. data/spec/unit/mongoid/extensions/boolean/conversions_spec.rb +49 -0
  212. data/spec/unit/mongoid/extensions/date/conversions_spec.rb +145 -0
  213. data/spec/unit/mongoid/extensions/datetime/conversions_spec.rb +14 -0
  214. data/spec/unit/mongoid/extensions/false_class/equality_spec.rb +35 -0
  215. data/spec/unit/mongoid/extensions/float/conversions_spec.rb +61 -0
  216. data/spec/unit/mongoid/extensions/hash/accessors_spec.rb +184 -0
  217. data/spec/unit/mongoid/extensions/hash/assimilation_spec.rb +59 -0
  218. data/spec/unit/mongoid/extensions/hash/conversions_spec.rb +35 -0
  219. data/spec/unit/mongoid/extensions/hash/criteria_helpers_spec.rb +17 -0
  220. data/spec/unit/mongoid/extensions/hash/scoping_spec.rb +14 -0
  221. data/spec/unit/mongoid/extensions/integer/conversions_spec.rb +61 -0
  222. data/spec/unit/mongoid/extensions/nil/assimilation_spec.rb +29 -0
  223. data/spec/unit/mongoid/extensions/object/conversions_spec.rb +44 -0
  224. data/spec/unit/mongoid/extensions/objectid/conversions_spec.rb +22 -0
  225. data/spec/unit/mongoid/extensions/proc/scoping_spec.rb +34 -0
  226. data/spec/unit/mongoid/extensions/set/conversions_spec.rb +21 -0
  227. data/spec/unit/mongoid/extensions/string/conversions_spec.rb +28 -0
  228. data/spec/unit/mongoid/extensions/string/inflections_spec.rb +208 -0
  229. data/spec/unit/mongoid/extensions/symbol/inflections_spec.rb +107 -0
  230. data/spec/unit/mongoid/extensions/time_conversions_spec.rb +186 -0
  231. data/spec/unit/mongoid/extensions/true_class/equality_spec.rb +35 -0
  232. data/spec/unit/mongoid/extras_spec.rb +102 -0
  233. data/spec/unit/mongoid/factory_spec.rb +31 -0
  234. data/spec/unit/mongoid/field_spec.rb +169 -0
  235. data/spec/unit/mongoid/fields_spec.rb +181 -0
  236. data/spec/unit/mongoid/finders_spec.rb +439 -0
  237. data/spec/unit/mongoid/hierarchy_spec.rb +68 -0
  238. data/spec/unit/mongoid/identity_spec.rb +109 -0
  239. data/spec/unit/mongoid/indexes_spec.rb +99 -0
  240. data/spec/unit/mongoid/javascript_spec.rb +48 -0
  241. data/spec/unit/mongoid/logger_spec.rb +38 -0
  242. data/spec/unit/mongoid/matchers/all_spec.rb +27 -0
  243. data/spec/unit/mongoid/matchers/default_spec.rb +27 -0
  244. data/spec/unit/mongoid/matchers/exists_spec.rb +56 -0
  245. data/spec/unit/mongoid/matchers/gt_spec.rb +39 -0
  246. data/spec/unit/mongoid/matchers/gte_spec.rb +49 -0
  247. data/spec/unit/mongoid/matchers/in_spec.rb +27 -0
  248. data/spec/unit/mongoid/matchers/lt_spec.rb +39 -0
  249. data/spec/unit/mongoid/matchers/lte_spec.rb +49 -0
  250. data/spec/unit/mongoid/matchers/ne_spec.rb +27 -0
  251. data/spec/unit/mongoid/matchers/nin_spec.rb +27 -0
  252. data/spec/unit/mongoid/matchers/size_spec.rb +27 -0
  253. data/spec/unit/mongoid/matchers_spec.rb +329 -0
  254. data/spec/unit/mongoid/memoization_spec.rb +75 -0
  255. data/spec/unit/mongoid/named_scope_spec.rb +123 -0
  256. data/spec/unit/mongoid/paranoia_spec.rb +108 -0
  257. data/spec/unit/mongoid/paths_spec.rb +272 -0
  258. data/spec/unit/mongoid/persistence/insert_embedded_spec.rb +154 -0
  259. data/spec/unit/mongoid/persistence/insert_spec.rb +144 -0
  260. data/spec/unit/mongoid/persistence/remove_all_spec.rb +82 -0
  261. data/spec/unit/mongoid/persistence/remove_embedded_spec.rb +152 -0
  262. data/spec/unit/mongoid/persistence/remove_spec.rb +89 -0
  263. data/spec/unit/mongoid/persistence/update_spec.rb +177 -0
  264. data/spec/unit/mongoid/persistence_spec.rb +452 -0
  265. data/spec/unit/mongoid/scope_spec.rb +240 -0
  266. data/spec/unit/mongoid/serialization_spec.rb +43 -0
  267. data/spec/unit/mongoid/state_spec.rb +94 -0
  268. data/spec/unit/mongoid/timestamps_spec.rb +30 -0
  269. data/spec/unit/mongoid/validations/associated_spec.rb +103 -0
  270. data/spec/unit/mongoid/validations/uniqueness_spec.rb +201 -0
  271. data/spec/unit/mongoid/validations_spec.rb +43 -0
  272. data/spec/unit/mongoid/versioning_spec.rb +41 -0
  273. data/spec/unit/mongoid_spec.rb +46 -0
  274. metadata +433 -0
@@ -0,0 +1,189 @@
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:
10
+ #
11
+ # <tt>criteria.ascending(:title, :dob)</tt>
12
+ def ascending(*fields)
13
+ @options[:sort] = [] unless @options[:sort] || fields.first.nil?
14
+ fields.flatten.each { |field| @options[:sort] << [ field, :asc ] }
15
+ self
16
+ end
17
+
18
+ alias :asc :ascending
19
+
20
+ # Tells the criteria that the cursor that gets returned needs to be
21
+ # cached. This is so multiple iterations don't hit the database multiple
22
+ # times, however this is not advisable when working with large data sets
23
+ # as the entire results will get stored in memory.
24
+ #
25
+ # Example:
26
+ #
27
+ # <tt>criteria.cache</tt>
28
+ def cache
29
+ @options.merge!(:cache => true); self
30
+ end
31
+
32
+ # Will return true if the cache option has been set.
33
+ #
34
+ # Example:
35
+ #
36
+ # <tt>criteria.cached?</tt>
37
+ def cached?
38
+ @options[:cache] == true
39
+ end
40
+
41
+ # Adds fields to be sorted in descending order. Will add them in the order
42
+ # they were passed into the method.
43
+ #
44
+ # Example:
45
+ #
46
+ # <tt>criteria.descending(:title, :dob)</tt>
47
+ def descending(*fields)
48
+ @options[:sort] = [] unless @options[:sort] || fields.first.nil?
49
+ fields.flatten.each { |field| @options[:sort] << [ field, :desc ] }
50
+ self
51
+ end
52
+
53
+ alias :desc :descending
54
+
55
+ # Flags the criteria to execute against a read-only slave in the pool
56
+ # instead of master.
57
+ #
58
+ # Example:
59
+ #
60
+ # <tt>criteria.enslave</tt>
61
+ def enslave
62
+ @options.merge!(:enslave => true); self
63
+ end
64
+
65
+ # Will return true if the criteria is enslaved.
66
+ #
67
+ # Example:
68
+ #
69
+ # <tt>criteria.enslaved?</tt>
70
+ def enslaved?
71
+ @options[:enslave] == true
72
+ end
73
+
74
+ # Adds a criterion to the +Criteria+ that specifies additional options
75
+ # to be passed to the Ruby driver, in the exact format for the driver.
76
+ #
77
+ # Options:
78
+ #
79
+ # extras: A +Hash+ that gets set to the driver options.
80
+ #
81
+ # Example:
82
+ #
83
+ # <tt>criteria.extras(:limit => 20, :skip => 40)</tt>
84
+ #
85
+ # Returns: <tt>self</tt>
86
+ def extras(extras)
87
+ @options.merge!(extras); filter_options; self
88
+ end
89
+
90
+ # Adds a criterion to the +Criteria+ that specifies an id that must be matched.
91
+ #
92
+ # Options:
93
+ #
94
+ # object_id: A +String+ representation of a <tt>BSON::ObjectID</tt>
95
+ #
96
+ # Example:
97
+ #
98
+ # <tt>criteria.id("4ab2bc4b8ad548971900005c")</tt>
99
+ #
100
+ # Returns: <tt>self</tt>
101
+ def id(*args)
102
+ (args.flatten.size > 1) ? self.in(:_id => args.flatten) : (@selector[:_id] = args.first)
103
+ self
104
+ end
105
+
106
+ # Adds a criterion to the +Criteria+ that specifies the maximum number of
107
+ # results to return. This is mostly used in conjunction with <tt>skip()</tt>
108
+ # to handle paginated results.
109
+ #
110
+ # Options:
111
+ #
112
+ # value: An +Integer+ specifying the max number of results. Defaults to 20.
113
+ #
114
+ # Example:
115
+ #
116
+ # <tt>criteria.limit(100)</tt>
117
+ #
118
+ # Returns: <tt>self</tt>
119
+ def limit(value = 20)
120
+ @options[:limit] = value; self
121
+ end
122
+
123
+ # Returns the offset option. If a per_page option is in the list then it
124
+ # will replace it with a skip parameter and return the same value. Defaults
125
+ # to 20 if nothing was provided.
126
+ def offset(*args)
127
+ args.size > 0 ? skip(args.first) : @options[:skip]
128
+ end
129
+
130
+ # Adds a criterion to the +Criteria+ that specifies the sort order of
131
+ # the returned documents in the database. Similar to a SQL "ORDER BY".
132
+ #
133
+ # Options:
134
+ #
135
+ # params: An +Array+ of [field, direction] sorting pairs.
136
+ #
137
+ # Example:
138
+ #
139
+ # <tt>criteria.order_by([[:field1, :asc], [:field2, :desc]])</tt>
140
+ #
141
+ # Returns: <tt>self</tt>
142
+ def order_by(*args)
143
+ @options[:sort] = [] unless @options[:sort] || args.first.nil?
144
+ arguments = args.first
145
+ case arguments
146
+ when Hash then arguments.each { |field, direction| @options[:sort] << [ field, direction ] }
147
+ when Array then @options[:sort].concat(arguments)
148
+ when Complex
149
+ args.flatten.each { |complex| @options[:sort] << [ complex.key, complex.operator.to_sym ] }
150
+ end; self
151
+ end
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
+ # <tt>limit()</tt> to handle paginated results, and is similar to the
156
+ # traditional "offset" parameter.
157
+ #
158
+ # Options:
159
+ #
160
+ # value: An +Integer+ specifying the number of results to skip. Defaults to 0.
161
+ #
162
+ # Example:
163
+ #
164
+ # <tt>criteria.skip(20)</tt>
165
+ #
166
+ # Returns: <tt>self</tt>
167
+ def skip(value = 0)
168
+ @options[:skip] = value; self
169
+ end
170
+
171
+ # Adds a criterion to the +Criteria+ that specifies a type or an Array of type that must be matched.
172
+ #
173
+ # Options:
174
+ #
175
+ # types : An +Array+ of types of a +String+ representing the Type of you search
176
+ #
177
+ # Example:
178
+ #
179
+ # <tt>criteria.type('Browser')</tt>
180
+ # <tt>criteria.type(['Firefox', 'Browser'])</tt>
181
+ #
182
+ # Returns: <tt>self</tt>
183
+ def type(types)
184
+ types = [types] unless types.is_a?(Array)
185
+ self.in(:_type => types)
186
+ end
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,81 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc
3
+ class Cursor
4
+ include Enumerable
5
+ # Operations on the Mongo::Cursor object that will not get overriden by the
6
+ # Mongoid::Cursor are defined here.
7
+ OPERATIONS = [
8
+ :close,
9
+ :closed?,
10
+ :count,
11
+ :explain,
12
+ :fields,
13
+ :full_collection_name,
14
+ :hint,
15
+ :limit,
16
+ :order,
17
+ :query_options_hash,
18
+ :query_opts,
19
+ :selector,
20
+ :skip,
21
+ :snapshot,
22
+ :sort,
23
+ :timeout
24
+ ]
25
+
26
+ attr_reader :collection
27
+
28
+ # The operations above will all delegate to the proxied Mongo::Cursor.
29
+ #
30
+ # Example:
31
+ #
32
+ # <tt>cursor.close</tt>
33
+ OPERATIONS.each do |name|
34
+ define_method(name) { |*args| @cursor.send(name, *args) }
35
+ end
36
+
37
+ # Iterate over each document in the cursor and yield to it.
38
+ #
39
+ # Example:
40
+ #
41
+ # <tt>cursor.each { |doc| p doc.title }</tt>
42
+ def each
43
+ @cursor.each do |document|
44
+ yield Mongoid::Factory.build(@klass, document)
45
+ end
46
+ end
47
+
48
+ # Create the new +Mongoid::Cursor+.
49
+ #
50
+ # Options:
51
+ #
52
+ # collection: The Mongoid::Collection instance.
53
+ # cursor: The Mongo::Cursor to be proxied.
54
+ #
55
+ # Example:
56
+ #
57
+ # <tt>Mongoid::Cursor.new(Person, cursor)</tt>
58
+ def initialize(klass, collection, cursor)
59
+ @klass, @collection, @cursor = klass, collection, cursor
60
+ end
61
+
62
+ # Return the next document in the cursor. Will instantiate a new Mongoid
63
+ # document with the attributes.
64
+ #
65
+ # Example:
66
+ #
67
+ # <tt>cursor.next_document</tt>
68
+ def next_document
69
+ Mongoid::Factory.build(@klass, @cursor.next_document)
70
+ end
71
+
72
+ # Returns an array of all the documents in the cursor.
73
+ #
74
+ # Example:
75
+ #
76
+ # <tt>cursor.to_a</tt>
77
+ def to_a
78
+ @cursor.to_a.collect { |attrs| Mongoid::Factory.build(@klass, attrs) }
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ class Deprecation #:nodoc
4
+ include Singleton
5
+
6
+ # Alert of a deprecation. This will delegate to the logger and call warn on
7
+ # it.
8
+ #
9
+ # Example:
10
+ #
11
+ # <tt>deprecation.alert("Method no longer used")</tt>
12
+ def alert(message)
13
+ @logger.warn("Deprecation: #{message}")
14
+ end
15
+
16
+ protected
17
+ def initialize
18
+ @logger = Mongoid::Logger.new
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,252 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Dirty #:nodoc:
4
+ extend ActiveSupport::Concern
5
+
6
+ # Gets the changes for a specific field.
7
+ #
8
+ # Example:
9
+ #
10
+ # person = Person.new(:title => "Sir")
11
+ # person.title = "Madam"
12
+ # person.attribute_change("title") # [ "Sir", "Madam" ]
13
+ #
14
+ # Returns:
15
+ #
16
+ # An +Array+ containing the old and new values.
17
+ def attribute_change(name)
18
+ modifications[name]
19
+ end
20
+
21
+ # Determines if a specific field has chaged.
22
+ #
23
+ # Example:
24
+ #
25
+ # person = Person.new(:title => "Sir")
26
+ # person.title = "Madam"
27
+ # person.attribute_changed?("title") # true
28
+ #
29
+ # Returns:
30
+ #
31
+ # +true+ if changed, +false+ if not.
32
+ def attribute_changed?(name)
33
+ modifications.include?(name)
34
+ end
35
+
36
+ # Gets the old value for a specific field.
37
+ #
38
+ # Example:
39
+ #
40
+ # person = Person.new(:title => "Sir")
41
+ # person.title = "Madam"
42
+ # person.attribute_was("title") # "Sir"
43
+ #
44
+ # Returns:
45
+ #
46
+ # The old field value.
47
+ def attribute_was(name)
48
+ change = modifications[name]
49
+ change ? change[0] : nil
50
+ end
51
+
52
+ # Gets the names of all the fields that have changed in the document.
53
+ #
54
+ # Example:
55
+ #
56
+ # person = Person.new(:title => "Sir")
57
+ # person.title = "Madam"
58
+ # person.changed # returns [ "title" ]
59
+ #
60
+ # Returns:
61
+ #
62
+ # An +Array+ of changed field names.
63
+ def changed
64
+ modifications.keys
65
+ end
66
+
67
+ # Alerts to whether the document has been modified or not.
68
+ #
69
+ # Example:
70
+ #
71
+ # person = Person.new(:title => "Sir")
72
+ # person.title = "Madam"
73
+ # person.changed? # returns true
74
+ #
75
+ # Returns:
76
+ #
77
+ # +true+ if changed, +false+ if not.
78
+ def changed?
79
+ !modifications.empty?
80
+ end
81
+
82
+ # Gets all the modifications that have happened to the object as a +Hash+
83
+ # with the keys being the names of the fields, and the values being an
84
+ # +Array+ with the old value and new value.
85
+ #
86
+ # Example:
87
+ #
88
+ # person = Person.new(:title => "Sir")
89
+ # person.title = "Madam"
90
+ # person.changes # returns { "title" => [ "Sir", "Madam" ] }
91
+ #
92
+ # Returns:
93
+ #
94
+ # A +Hash+ of changes.
95
+ def changes
96
+ modifications
97
+ end
98
+
99
+ # Call this method after save, so the changes can be properly switched.
100
+ #
101
+ # Example:
102
+ #
103
+ # <tt>person.move_changes</tt>
104
+ def move_changes
105
+ @previous_modifications = modifications.dup
106
+ @modifications = {}
107
+ end
108
+
109
+ # Gets all the new values for each of the changed fields, to be passed to
110
+ # a MongoDB $set modifier.
111
+ #
112
+ # Example:
113
+ #
114
+ # person = Person.new(:title => "Sir")
115
+ # person.title = "Madam"
116
+ # person.setters # returns { "title" => "Madam" }
117
+ #
118
+ # Returns:
119
+ #
120
+ # A +Hash+ of new values.
121
+ def setters
122
+ modifications.inject({}) do |sets, (field, changes)|
123
+ key = embedded? ? "#{_position}.#{field}" : field
124
+ sets[key] = changes[1]; sets
125
+ end
126
+ end
127
+
128
+ # Gets all the modifications that have happened to the object before the
129
+ # object was saved.
130
+ #
131
+ # Example:
132
+ #
133
+ # person = Person.new(:title => "Sir")
134
+ # person.title = "Madam"
135
+ # person.save!
136
+ # person.previous_changes # returns { "title" => [ "Sir", "Madam" ] }
137
+ #
138
+ # Returns:
139
+ #
140
+ # A +Hash+ of changes before save.
141
+ def previous_changes
142
+ @previous_modifications
143
+ end
144
+
145
+ # Resets a changed field back to its old value.
146
+ #
147
+ # Example:
148
+ #
149
+ # person = Person.new(:title => "Sir")
150
+ # person.title = "Madam"
151
+ # person.reset_attribute!("title")
152
+ # person.title # "Sir"
153
+ #
154
+ # Returns:
155
+ #
156
+ # The old field value.
157
+ def reset_attribute!(name)
158
+ value = attribute_was(name)
159
+ if value
160
+ @attributes[name] = value
161
+ modifications.delete(name)
162
+ end
163
+ end
164
+
165
+ # Sets up the modifications hash. This occurs just after the document is
166
+ # instantiated.
167
+ #
168
+ # Example:
169
+ #
170
+ # <tt>document.setup_notifications</tt>
171
+ def setup_modifications
172
+ @accessed ||= {}
173
+ @modifications ||= {}
174
+ @previous_modifications ||= {}
175
+ end
176
+
177
+ # Reset all modifications for the document. This will wipe all the marked
178
+ # changes, but not reset the values.
179
+ #
180
+ # Example:
181
+ #
182
+ # <tt>document.reset_modifications</tt>
183
+ def reset_modifications
184
+ @accessed = {}
185
+ @modifications = {}
186
+ end
187
+
188
+ protected
189
+
190
+ # Audit the original value for a field that can be modified in place.
191
+ #
192
+ # Example:
193
+ #
194
+ # <tt>person.accessed("aliases", [ "007" ])</tt>
195
+ def accessed(name, value)
196
+ @accessed ||= {}
197
+ @accessed[name] = value.dup if (value.is_a?(Array) || value.is_a?(Hash)) && !@accessed.has_key?(name)
198
+ value
199
+ end
200
+
201
+ # Get all normal modifications plus in place potential changes.
202
+ #
203
+ # Example:
204
+ #
205
+ # <tt>person.modifications</tt>
206
+ #
207
+ # Returns:
208
+ #
209
+ # All changes to the document.
210
+ def modifications
211
+ @accessed.each_pair do |field, value|
212
+ current = @attributes[field]
213
+ @modifications[field] = [ value, current ] if current != value
214
+ end
215
+ @accessed.clear
216
+ @modifications
217
+ end
218
+
219
+ # Audit the change of a field's value.
220
+ #
221
+ # Example:
222
+ #
223
+ # <tt>person.modify("name", "Jack", "John")</tt>
224
+ def modify(name, old_value, new_value)
225
+ @attributes[name] = new_value
226
+ if @modifications && (old_value != new_value)
227
+ original = @modifications[name].first if @modifications[name]
228
+ @modifications[name] = [ (original || old_value), new_value ]
229
+ end
230
+ end
231
+
232
+ module ClassMethods #:nodoc:
233
+ # Add the dynamic dirty methods. These are custom methods defined on a
234
+ # field by field basis that wrap the dirty attribute methods.
235
+ #
236
+ # Example:
237
+ #
238
+ # person = Person.new(:title => "Sir")
239
+ # person.title = "Madam"
240
+ # person.title_change # [ "Sir", "Madam" ]
241
+ # person.title_changed? # true
242
+ # person.title_was # "Sir"
243
+ # person.reset_title!
244
+ def add_dirty_methods(name)
245
+ define_method("#{name}_change") { attribute_change(name) } unless instance_methods.include?("#{name}_change")
246
+ define_method("#{name}_changed?") { attribute_changed?(name) } unless instance_methods.include?("#{name}_changed?")
247
+ define_method("#{name}_was") { attribute_was(name) } unless instance_methods.include?("#{name}_was")
248
+ define_method("reset_#{name}!") { reset_attribute!(name) } unless instance_methods.include?("reset_#{name}!")
249
+ end
250
+ end
251
+ end
252
+ end