stonegao-mongoid 2.0.0.rc.6

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 (199) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +50 -0
  3. data/Rakefile +51 -0
  4. data/lib/config/locales/bg.yml +44 -0
  5. data/lib/config/locales/de.yml +44 -0
  6. data/lib/config/locales/en.yml +45 -0
  7. data/lib/config/locales/es.yml +44 -0
  8. data/lib/config/locales/fr.yml +45 -0
  9. data/lib/config/locales/hu.yml +47 -0
  10. data/lib/config/locales/it.yml +42 -0
  11. data/lib/config/locales/kr.yml +68 -0
  12. data/lib/config/locales/nl.yml +42 -0
  13. data/lib/config/locales/pl.yml +42 -0
  14. data/lib/config/locales/pt-br.yml +43 -0
  15. data/lib/config/locales/pt.yml +43 -0
  16. data/lib/config/locales/ro.yml +49 -0
  17. data/lib/config/locales/sv.yml +43 -0
  18. data/lib/config/locales/zh-CN.yml +34 -0
  19. data/lib/mongoid/atomicity.rb +111 -0
  20. data/lib/mongoid/attributes.rb +251 -0
  21. data/lib/mongoid/callbacks.rb +13 -0
  22. data/lib/mongoid/collection.rb +137 -0
  23. data/lib/mongoid/collections/cyclic_iterator.rb +34 -0
  24. data/lib/mongoid/collections/master.rb +29 -0
  25. data/lib/mongoid/collections/operations.rb +42 -0
  26. data/lib/mongoid/collections/slaves.rb +45 -0
  27. data/lib/mongoid/collections.rb +70 -0
  28. data/lib/mongoid/components.rb +45 -0
  29. data/lib/mongoid/config/database.rb +167 -0
  30. data/lib/mongoid/config/replset_database.rb +48 -0
  31. data/lib/mongoid/config.rb +343 -0
  32. data/lib/mongoid/contexts/enumerable/sort.rb +43 -0
  33. data/lib/mongoid/contexts/enumerable.rb +226 -0
  34. data/lib/mongoid/contexts/ids.rb +25 -0
  35. data/lib/mongoid/contexts/mongo.rb +345 -0
  36. data/lib/mongoid/contexts/paging.rb +50 -0
  37. data/lib/mongoid/contexts.rb +21 -0
  38. data/lib/mongoid/copyable.rb +44 -0
  39. data/lib/mongoid/criteria.rb +325 -0
  40. data/lib/mongoid/criterion/complex.rb +34 -0
  41. data/lib/mongoid/criterion/creational.rb +34 -0
  42. data/lib/mongoid/criterion/exclusion.rb +67 -0
  43. data/lib/mongoid/criterion/inclusion.rb +134 -0
  44. data/lib/mongoid/criterion/inspection.rb +20 -0
  45. data/lib/mongoid/criterion/optional.rb +213 -0
  46. data/lib/mongoid/criterion/selector.rb +74 -0
  47. data/lib/mongoid/cursor.rb +81 -0
  48. data/lib/mongoid/default_scope.rb +28 -0
  49. data/lib/mongoid/dirty.rb +251 -0
  50. data/lib/mongoid/document.rb +256 -0
  51. data/lib/mongoid/errors/document_not_found.rb +29 -0
  52. data/lib/mongoid/errors/invalid_collection.rb +19 -0
  53. data/lib/mongoid/errors/invalid_database.rb +20 -0
  54. data/lib/mongoid/errors/invalid_field.rb +19 -0
  55. data/lib/mongoid/errors/invalid_options.rb +16 -0
  56. data/lib/mongoid/errors/invalid_type.rb +26 -0
  57. data/lib/mongoid/errors/mongoid_error.rb +27 -0
  58. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +21 -0
  59. data/lib/mongoid/errors/unsaved_document.rb +23 -0
  60. data/lib/mongoid/errors/unsupported_version.rb +21 -0
  61. data/lib/mongoid/errors/validations.rb +24 -0
  62. data/lib/mongoid/errors.rb +12 -0
  63. data/lib/mongoid/extensions/array/conversions.rb +23 -0
  64. data/lib/mongoid/extensions/array/parentization.rb +13 -0
  65. data/lib/mongoid/extensions/big_decimal/conversions.rb +19 -0
  66. data/lib/mongoid/extensions/binary/conversions.rb +17 -0
  67. data/lib/mongoid/extensions/boolean/conversions.rb +27 -0
  68. data/lib/mongoid/extensions/date/conversions.rb +25 -0
  69. data/lib/mongoid/extensions/datetime/conversions.rb +12 -0
  70. data/lib/mongoid/extensions/false_class/equality.rb +13 -0
  71. data/lib/mongoid/extensions/float/conversions.rb +20 -0
  72. data/lib/mongoid/extensions/hash/conversions.rb +19 -0
  73. data/lib/mongoid/extensions/hash/criteria_helpers.rb +22 -0
  74. data/lib/mongoid/extensions/hash/scoping.rb +12 -0
  75. data/lib/mongoid/extensions/integer/conversions.rb +20 -0
  76. data/lib/mongoid/extensions/nil/collectionization.rb +12 -0
  77. data/lib/mongoid/extensions/object/conversions.rb +25 -0
  78. data/lib/mongoid/extensions/object/reflections.rb +17 -0
  79. data/lib/mongoid/extensions/object/yoda.rb +27 -0
  80. data/lib/mongoid/extensions/object_id/conversions.rb +57 -0
  81. data/lib/mongoid/extensions/proc/scoping.rb +12 -0
  82. data/lib/mongoid/extensions/set/conversions.rb +20 -0
  83. data/lib/mongoid/extensions/string/conversions.rb +34 -0
  84. data/lib/mongoid/extensions/string/inflections.rb +97 -0
  85. data/lib/mongoid/extensions/symbol/conversions.rb +21 -0
  86. data/lib/mongoid/extensions/symbol/inflections.rb +40 -0
  87. data/lib/mongoid/extensions/time_conversions.rb +38 -0
  88. data/lib/mongoid/extensions/true_class/equality.rb +13 -0
  89. data/lib/mongoid/extensions.rb +116 -0
  90. data/lib/mongoid/extras.rb +61 -0
  91. data/lib/mongoid/factory.rb +20 -0
  92. data/lib/mongoid/field.rb +95 -0
  93. data/lib/mongoid/fields.rb +138 -0
  94. data/lib/mongoid/finders.rb +173 -0
  95. data/lib/mongoid/hierarchy.rb +85 -0
  96. data/lib/mongoid/identity.rb +89 -0
  97. data/lib/mongoid/indexes.rb +38 -0
  98. data/lib/mongoid/inspection.rb +58 -0
  99. data/lib/mongoid/javascript/functions.yml +37 -0
  100. data/lib/mongoid/javascript.rb +21 -0
  101. data/lib/mongoid/json.rb +16 -0
  102. data/lib/mongoid/keys.rb +77 -0
  103. data/lib/mongoid/logger.rb +18 -0
  104. data/lib/mongoid/matchers/all.rb +11 -0
  105. data/lib/mongoid/matchers/default.rb +27 -0
  106. data/lib/mongoid/matchers/exists.rb +13 -0
  107. data/lib/mongoid/matchers/gt.rb +11 -0
  108. data/lib/mongoid/matchers/gte.rb +11 -0
  109. data/lib/mongoid/matchers/in.rb +11 -0
  110. data/lib/mongoid/matchers/lt.rb +11 -0
  111. data/lib/mongoid/matchers/lte.rb +11 -0
  112. data/lib/mongoid/matchers/ne.rb +11 -0
  113. data/lib/mongoid/matchers/nin.rb +11 -0
  114. data/lib/mongoid/matchers/size.rb +11 -0
  115. data/lib/mongoid/matchers.rb +55 -0
  116. data/lib/mongoid/modifiers/command.rb +18 -0
  117. data/lib/mongoid/modifiers/inc.rb +24 -0
  118. data/lib/mongoid/modifiers.rb +24 -0
  119. data/lib/mongoid/multi_database.rb +11 -0
  120. data/lib/mongoid/multi_parameter_attributes.rb +80 -0
  121. data/lib/mongoid/named_scope.rb +36 -0
  122. data/lib/mongoid/nested_attributes.rb +43 -0
  123. data/lib/mongoid/paranoia.rb +103 -0
  124. data/lib/mongoid/paths.rb +61 -0
  125. data/lib/mongoid/persistence/command.rb +59 -0
  126. data/lib/mongoid/persistence/insert.rb +53 -0
  127. data/lib/mongoid/persistence/insert_embedded.rb +42 -0
  128. data/lib/mongoid/persistence/remove.rb +44 -0
  129. data/lib/mongoid/persistence/remove_all.rb +40 -0
  130. data/lib/mongoid/persistence/remove_embedded.rb +48 -0
  131. data/lib/mongoid/persistence/update.rb +76 -0
  132. data/lib/mongoid/persistence.rb +237 -0
  133. data/lib/mongoid/railtie.rb +129 -0
  134. data/lib/mongoid/railties/database.rake +171 -0
  135. data/lib/mongoid/railties/document.rb +12 -0
  136. data/lib/mongoid/relations/accessors.rb +157 -0
  137. data/lib/mongoid/relations/auto_save.rb +34 -0
  138. data/lib/mongoid/relations/binding.rb +26 -0
  139. data/lib/mongoid/relations/bindings/embedded/in.rb +82 -0
  140. data/lib/mongoid/relations/bindings/embedded/many.rb +98 -0
  141. data/lib/mongoid/relations/bindings/embedded/one.rb +66 -0
  142. data/lib/mongoid/relations/bindings/referenced/in.rb +74 -0
  143. data/lib/mongoid/relations/bindings/referenced/many.rb +96 -0
  144. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +99 -0
  145. data/lib/mongoid/relations/bindings/referenced/one.rb +66 -0
  146. data/lib/mongoid/relations/bindings.rb +9 -0
  147. data/lib/mongoid/relations/builder.rb +42 -0
  148. data/lib/mongoid/relations/builders/embedded/in.rb +25 -0
  149. data/lib/mongoid/relations/builders/embedded/many.rb +32 -0
  150. data/lib/mongoid/relations/builders/embedded/one.rb +26 -0
  151. data/lib/mongoid/relations/builders/nested_attributes/many.rb +116 -0
  152. data/lib/mongoid/relations/builders/nested_attributes/one.rb +135 -0
  153. data/lib/mongoid/relations/builders/referenced/in.rb +32 -0
  154. data/lib/mongoid/relations/builders/referenced/many.rb +26 -0
  155. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +29 -0
  156. data/lib/mongoid/relations/builders/referenced/one.rb +30 -0
  157. data/lib/mongoid/relations/builders.rb +79 -0
  158. data/lib/mongoid/relations/cascading/delete.rb +19 -0
  159. data/lib/mongoid/relations/cascading/destroy.rb +19 -0
  160. data/lib/mongoid/relations/cascading/nullify.rb +18 -0
  161. data/lib/mongoid/relations/cascading/strategy.rb +26 -0
  162. data/lib/mongoid/relations/cascading.rb +55 -0
  163. data/lib/mongoid/relations/constraint.rb +45 -0
  164. data/lib/mongoid/relations/cyclic.rb +97 -0
  165. data/lib/mongoid/relations/embedded/in.rb +173 -0
  166. data/lib/mongoid/relations/embedded/many.rb +483 -0
  167. data/lib/mongoid/relations/embedded/one.rb +170 -0
  168. data/lib/mongoid/relations/macros.rb +306 -0
  169. data/lib/mongoid/relations/many.rb +171 -0
  170. data/lib/mongoid/relations/metadata.rb +533 -0
  171. data/lib/mongoid/relations/nested_builder.rb +68 -0
  172. data/lib/mongoid/relations/one.rb +47 -0
  173. data/lib/mongoid/relations/polymorphic.rb +54 -0
  174. data/lib/mongoid/relations/proxy.rb +128 -0
  175. data/lib/mongoid/relations/referenced/in.rb +216 -0
  176. data/lib/mongoid/relations/referenced/many.rb +443 -0
  177. data/lib/mongoid/relations/referenced/many_to_many.rb +344 -0
  178. data/lib/mongoid/relations/referenced/one.rb +206 -0
  179. data/lib/mongoid/relations/reflections.rb +45 -0
  180. data/lib/mongoid/relations.rb +105 -0
  181. data/lib/mongoid/safe.rb +23 -0
  182. data/lib/mongoid/safety.rb +207 -0
  183. data/lib/mongoid/scope.rb +31 -0
  184. data/lib/mongoid/serialization.rb +99 -0
  185. data/lib/mongoid/state.rb +66 -0
  186. data/lib/mongoid/timestamps.rb +38 -0
  187. data/lib/mongoid/validations/associated.rb +42 -0
  188. data/lib/mongoid/validations/uniqueness.rb +85 -0
  189. data/lib/mongoid/validations.rb +117 -0
  190. data/lib/mongoid/version.rb +4 -0
  191. data/lib/mongoid/versioning.rb +51 -0
  192. data/lib/mongoid.rb +139 -0
  193. data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
  194. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +23 -0
  195. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  196. data/lib/rails/generators/mongoid/model/templates/model.rb +17 -0
  197. data/lib/rails/generators/mongoid_generator.rb +61 -0
  198. data/lib/rails/mongoid.rb +57 -0
  199. metadata +380 -0
@@ -0,0 +1,43 @@
1
+ pt:
2
+ activemodel:
3
+ errors:
4
+ messages:
5
+ taken: já está utilizada
6
+
7
+ mongoid:
8
+ errors:
9
+ messages:
10
+ document_not_found:
11
+ Nenhum documento encontrado para a classe %{klass} com os id(s) %{identifiers}.
12
+ invalid_database:
13
+ A base de dados deverá ser uma Mongo::DB, em vez de %{name}.
14
+ invalid_type:
15
+ O campo foi definido como %{klass}, mas recebeu uma instância de %{other} com
16
+ o valor %{value}.
17
+ unsupported_version:
18
+ MongoDB %{version} não é suportada, por favor actualize para a
19
+ versão %{mongo_version}.
20
+ validations:
21
+ A validação falhou - %{errors}.
22
+ invalid_collection:
23
+ O acesso à colecção para %{klass} não é permitido porque
24
+ é um documento embebido, por favor aceda à colecção através
25
+ do documento raiz.
26
+ invalid_field:
27
+ Não é permitido definir um campo com o nome %{name}. Não defina
28
+ campos que entrem em conflito com os nomes dos atributos internos e métodos
29
+ do Mongoid. Use Document#instance_methods para consultar esses nomes.
30
+ too_many_nested_attribute_records:
31
+ A aceitação de atributos encadeados para %{association} encontra-se limitada
32
+ a %{limit} registros.
33
+ embedded_in_must_have_inverse_of:
34
+ As opções para uma associação embedded_in devem incluir inverse_of.
35
+ dependent_only_references_one_or_many:
36
+ A opção The dependent => destroy|delete que é fornecida
37
+ é apenas válida para associações references_one ou references_many.
38
+ association_cant_have_inverse_of:
39
+ A definição de inverse_of nesta associação não é permitida. Apenas
40
+ use esta opção em embedded_in ou references_many como lista.
41
+ unsaved_document:
42
+ You cannot call create or create! through a relational association
43
+ relation (%{document}) who's parent (%{base}) is not already saved.
@@ -0,0 +1,49 @@
1
+ ro:
2
+ activemodel:
3
+ errors:
4
+ messages:
5
+ taken: este deja folosit
6
+
7
+ mongoid:
8
+ errors:
9
+ messages:
10
+ document_not_found:
11
+ Nu există document în clasa %{klass} cu id %{identifiers}.
12
+ invalid_database:
13
+ Baza de date ar trebui să fie de tipul Mongo::DB, nu %{name}.
14
+ invalid_type:
15
+ Câmpul a fost definit ca şi un(o) %{klass}, dar valoarea
16
+ recepţionată %{value} este de clasa %{other}.
17
+ unsupported_version:
18
+ Versiunea MongoDB %{version} nu este suportată.
19
+ Vă rugăm să folosiţi versiunea %{mongo_version}.
20
+ validations:
21
+ Validare nereuşită - %{errors}.
22
+ invalid_collection:
23
+ Accesul la colecţie din clasa %{klass} este interzisă, fiindcă
24
+ este un document încorporat. Vă rugăm accesaţi colecţia din
25
+ documentul rădăcină.
26
+ invalid_field:
27
+ Folosirea denumirii %{name} ptr. un câmp este interzisă. Vă
28
+ rugăm să evitaţi utilizarea acelor cuvinte care intră în conflict
29
+ cu denumirile folosite de proprietăţile sau metodele Mongoid-lui.
30
+ Folosiţi comanda Document#instance_methods pentru a afla care
31
+ sunt acestea.
32
+ too_many_nested_attribute_records:
33
+ În cazul %{association} folosirea atributelor îmbricate este
34
+ limitat la %{limit} înregistrări.
35
+ embedded_in_must_have_inverse_of:
36
+ Folosirea opţiunii inverse_of este obligatorie în cazul
37
+ asociaţiilor de tip embedded_in.
38
+ dependent_only_references_one_or_many:
39
+ Opţiunea dependent => destroy|delete poate fi folosită doar în
40
+ cazul asociaţiilor de tip references_one sau references_many.
41
+ association_cant_have_inverse_of:
42
+ Folosire opţiunii inverse_of la acest tip de asociaţie este
43
+ interzisă. Aceasta poate fi folosită doar la asociaţiile de
44
+ tip embedded_in sau references_many as array.
45
+ calling_document_find_with_nil_is_invalid:
46
+ Folosirea metodei Document#find cu valoarea nil este invalidă.
47
+ unsaved_document:
48
+ You cannot call create or create! through a relational association
49
+ relation (%{document}) who's parent (%{base}) is not already saved.
@@ -0,0 +1,43 @@
1
+ sv:
2
+ activemodel:
3
+ errors:
4
+ messages:
5
+ taken: har redan använts
6
+
7
+ mongoid:
8
+ errors:
9
+ messages:
10
+ document_not_found:
11
+ Inget dokument kunde hittas för klass %{klass} med id %{identifiers}.
12
+ invalid_database:
13
+ Databasen bör vara Mongo::DB, inte %{name}.
14
+ invalid_type:
15
+ Fältet var definerat som %{klass}, men fick %{other} med
16
+ värdet %{value}.
17
+ unsupported_version:
18
+ MongoDB %{version} stöds ej, vänligen upgradera
19
+ till %{mongo_version}.
20
+ validations:
21
+ Validering misslyckades - %{errors}.
22
+ invalid_collection:
23
+ Tillgång till kollektionen för %{klass} är inte tillåten eftersom den
24
+ är ett inbäddat dokument, vänligen accessa kollektionen från
25
+ rotdokumentet.
26
+ invalid_field:
27
+ Att definera ett fält med namnet %{name} är inte tillåtet. Definera inte
28
+ fält som är i konflikt med Mongoids interna attribut eller metod
29
+ namn. Använd Document#instance_methods för att se vilka namn detta innefattar.
30
+ too_many_nested_attribute_records:
31
+ Acceptans av nästlade attribut för %{association} är begränsat
32
+ till %{limit} register.
33
+ embedded_in_must_have_inverse_of:
34
+ Alternativ för en embedded_in association måste innehålla inverse_of.
35
+ dependent_only_references_one_or_many:
36
+ Alternativet dependent => destroy|delete som angavs
37
+ är endast giltigt för references_one eller references_many associationer.
38
+ association_cant_have_inverse_of:
39
+ Att definera inverse_of på denna association är inte tillåtet. Använd
40
+ endast detta alternativ på embedded_in eller references_many as array.
41
+ unsaved_document:
42
+ You cannot call create or create! through a relational association
43
+ relation (%{document}) who's parent (%{base}) is not already saved.
@@ -0,0 +1,34 @@
1
+ en:
2
+ activemodel:
3
+ errors:
4
+ messages:
5
+ taken: 已占用
6
+
7
+ mongoid:
8
+ errors:
9
+ messages:
10
+ document_not_found:
11
+ 没有发现类是%{klass}id(s)是%{identifiers}的文档
12
+ invalid_database:
13
+ 数据库应该是Mongo::DB,而不是%{name}.
14
+ invalid_type:
15
+ 在类%{klass}中定义了字段,实际值是%{value}的%{other}.
16
+ unsupported_version:
17
+ MongoDB %{version} 版本已过期,请升级到 %{mongo_version}.
18
+ validations:
19
+ 校验失败 - %{errors}.
20
+ invalid_collection:
21
+ 不允许直接访问嵌入式的集合%{klass} , 请从文档的根访问集合.
22
+ invalid_field:
23
+ 字段的名字不允许为 %{name}. 你不应该定义跟Mongoid内部属性或者方法相同的名字,详细请看Use Document#instance_methods.
24
+ too_many_nested_attribute_records:
25
+ 被关联的%{association} 嵌入式属性不能超过 %{limit}.
26
+ embedded_in_must_have_inverse_of:
27
+ embedded_in的关联属性必须包含inverse_of.
28
+ dependent_only_references_one_or_many:
29
+ dependent => destroy|delete 选项只有在references_one或者references_many时候有效.
30
+ association_cant_have_inverse_of:
31
+ 在当前的关联中,不允许定义inverse_of去,其只有在embedded_in或者references_many是数组的情况下使用
32
+ unsaved_document:
33
+ You cannot call create or create! through a relational association
34
+ relation (%{document}) who's parent (%{base}) is not already saved.
@@ -0,0 +1,111 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+
4
+ # This module contains the logic for supporting atomic operations against the
5
+ # database.
6
+ #
7
+ # @todo Durran: Refactor class out into separate objects for each type of
8
+ # update.
9
+ module Atomicity
10
+ extend ActiveSupport::Concern
11
+
12
+ # Get all the atomic updates that need to happen for the current
13
+ # +Document+. This includes all changes that need to happen in the
14
+ # entire hierarchy that exists below where the save call was made.
15
+ #
16
+ # @note
17
+ # MongoDB does not allow "conflicting modifications" to be
18
+ # performed in a single operation. Conflicting modifications are
19
+ # detected by the 'haveConflictingMod' function in MongoDB.
20
+ # Examination of the code suggests that two modifications (a $set
21
+ # and a $pushAll, for example) conflict if:
22
+ # (1) the key paths being modified are equal.
23
+ # (2) one key path is a prefix of the other.
24
+ # So a $set of 'addresses.0.street' will conflict with a $pushAll
25
+ # to 'addresses', and we will need to split our update into two
26
+ # pieces. We do not, however, attempt to match MongoDB's logic
27
+ # exactly. Instead, we assume that two updates conflict if the
28
+ # first component of the two key paths matches.
29
+ #
30
+ # @example Get the updates that need to occur.
31
+ # person._updates
32
+ #
33
+ # @return [ Hash ] The updates and their modifiers.
34
+ def _updates
35
+ processed = {}
36
+
37
+ _children.inject({ "$set" => _sets, "$pushAll" => {}, :other => {} }) do |updates, child|
38
+ changes = child._sets
39
+ updates["$set"].update(changes)
40
+ unless changes.empty?
41
+ processed[child._conficting_modification_key] = true
42
+ end
43
+
44
+ if processed.has_key?(child._conficting_modification_key)
45
+ target = :other
46
+ else
47
+ target = "$pushAll"
48
+ end
49
+
50
+ child._pushes.each do |attr, val|
51
+ if updates[target].has_key?(attr)
52
+ updates[target][attr] << val
53
+ else
54
+ updates[target].update({attr => [val]})
55
+ end
56
+ end
57
+ updates
58
+ end.delete_if do |key, value|
59
+ value.empty?
60
+ end
61
+ end
62
+
63
+ protected
64
+
65
+ # Get the key used to check for conflicting modifications. For now, we
66
+ # just use the first component of _path, and discard the first period
67
+ # and everything that follows.
68
+ #
69
+ # @example Get the key.
70
+ # person._conflicting_modification_key
71
+ #
72
+ # @return [ String ] The conflicting key.
73
+ def _conficting_modification_key
74
+ _path.sub(/\..*/, '')
75
+ end
76
+
77
+ # Get all the push attributes that need to occur.
78
+ #
79
+ # @example Get the pushes.
80
+ # person._pushes
81
+ #
82
+ # @return [ Hash ] The $pushAll operations.
83
+ def _pushes
84
+ pushable? ? { _path => to_hash } : {}
85
+ end
86
+
87
+ # Determine if the document can be pushed.
88
+ #
89
+ # @example Is this pushable?
90
+ # person.pushable?
91
+ #
92
+ # @return [ true, false ] Is the document new and embedded?
93
+ def pushable?
94
+ new_record? && embedded_many? && _parent.persisted?
95
+ end
96
+
97
+ # Get all the attributes that need to be set.
98
+ #
99
+ # @example Get the sets.
100
+ # person._sets
101
+ #
102
+ # @return [ Hash ] The $set operations.
103
+ def _sets
104
+ if changed? && !new_record?
105
+ setters
106
+ else
107
+ embedded_one? && new_record? ? { _path => to_hash } : {}
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,251 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+
4
+ # This module contains the logic for handling the internal attributes hash,
5
+ # and how to get and set values.
6
+ module Attributes
7
+
8
+ # Returns the object type. This corresponds to the name of the class that
9
+ # this document is, which is used in determining the class to
10
+ # instantiate in various cases.
11
+ #
12
+ # @example Get the type.
13
+ # person._type
14
+ #
15
+ # @return [ String ] The name of the class the document is.
16
+ def _type
17
+ @attributes["_type"]
18
+ end
19
+
20
+ # Set the type of the document. This should be the name of the class.
21
+ #
22
+ # @example Set the type
23
+ # person._type = "Person"
24
+ #
25
+ # @param [ String ] new_type The name of the class.
26
+ #
27
+ # @return [ String ] the new type.
28
+ def _type=(new_type)
29
+ @attributes["_type"] = new_type
30
+ end
31
+
32
+ # Determine if an attribute is present.
33
+ #
34
+ # @example Is the attribute present?
35
+ # person.attribute_present?("title")
36
+ #
37
+ # @param [ String, Symbol ] name The name of the attribute.
38
+ #
39
+ # @return [ true, false ] True if present, false if not.
40
+ def attribute_present?(name)
41
+ !read_attribute(name).blank?
42
+ end
43
+
44
+ # Get the id associated with this object. This will pull the _id value out
45
+ # of the attributes.
46
+ #
47
+ # @example Get the id.
48
+ # person.id
49
+ #
50
+ # @return [ BSON::ObjectId, String ] The id of the document.
51
+ def id
52
+ @attributes["_id"]
53
+ end
54
+ alias :_id :id
55
+
56
+ # Set the id of the document to a new one.
57
+ #
58
+ # @example Set the id.
59
+ # person.id = BSON::ObjectId.new
60
+ #
61
+ # @param [ BSON::ObjectId, String ] new_id The new id.
62
+ #
63
+ # @return [ BSON::ObjectId, String ] The new id.
64
+ def id=(new_id)
65
+ @attributes["_id"] = _id_type.set(new_id)
66
+ end
67
+ alias :_id= :id=
68
+
69
+ # Used for allowing accessor methods for dynamic attributes.
70
+ #
71
+ # @param [ String, Symbol ] name The name of the method.
72
+ # @param [ Array ] *args The arguments to the method.
73
+ def method_missing(name, *args)
74
+ attr = name.to_s
75
+ return super unless @attributes.has_key?(attr.reader)
76
+ if attr.writer?
77
+ # "args.size > 1" allows to simulate 1.8 behavior of "*args"
78
+ write_attribute(attr.reader, (args.size > 1) ? args : args.first)
79
+ else
80
+ read_attribute(attr.reader)
81
+ end
82
+ end
83
+
84
+ # Process the provided attributes casting them to their proper values if a
85
+ # field exists for them on the document. This will be limited to only the
86
+ # attributes provided in the suppied +Hash+ so that no extra nil values get
87
+ # put into the document's attributes.
88
+ #
89
+ # @example Process the attributes.
90
+ # person.process(:title => "sir", :age => 40)
91
+ #
92
+ # @param [ Hash ] attrs The attributes to set.
93
+ def process(attrs = nil)
94
+ pending = {}
95
+ sanitize_for_mass_assignment(attrs || {}).each_pair do |key, value|
96
+ if set_allowed?(key)
97
+ write_attribute(key, value)
98
+ else
99
+ pending[key.to_s] = value and next if relations.has_key?(key.to_s)
100
+ send("#{key}=", value)
101
+ end
102
+ end
103
+ yield self if block_given?
104
+ process_relations(pending)
105
+ setup_modifications
106
+ end
107
+
108
+ # Read a value from the document attributes. If the value does not exist
109
+ # it will return nil.
110
+ #
111
+ # @example Read an attribute.
112
+ # person.read_attribute(:title)
113
+ #
114
+ # @example Read an attribute (alternate syntax.)
115
+ # person[:title]
116
+ #
117
+ # @param [ String, Symbol ] name The name of the attribute to get.
118
+ #
119
+ # @return [ Object ] The value of the attribute.
120
+ def read_attribute(name)
121
+ access = name.to_s
122
+ value = @attributes[access]
123
+ typed_value = fields.has_key?(access) ? fields[access].get(value) : value
124
+ accessed(access, typed_value)
125
+ end
126
+ alias :[] :read_attribute
127
+
128
+ # Remove a value from the +Document+ attributes. If the value does not exist
129
+ # it will fail gracefully.
130
+ #
131
+ # @example Remove the attribute.
132
+ # person.remove_attribute(:title)
133
+ #
134
+ # @param [ String, Symbol ] name The name of the attribute to remove.
135
+ def remove_attribute(name)
136
+ access = name.to_s
137
+ modify(access, @attributes.delete(name.to_s), nil)
138
+ end
139
+
140
+ # Override respond_to? so it responds properly for dynamic attributes.
141
+ #
142
+ # @example Does this object respond to the method?
143
+ # person.respond_to?(:title)
144
+ #
145
+ # @param [ Array ] *args The name of the method.
146
+ #
147
+ # @return [ true, false ] True if it does, false if not.
148
+ def respond_to?(*args)
149
+ (Mongoid.allow_dynamic_fields &&
150
+ @attributes &&
151
+ @attributes.has_key?(args.first.to_s)
152
+ ) || super
153
+ end
154
+
155
+ # Write a single attribute to the document attribute hash. This will
156
+ # also fire the before and after update callbacks, and perform any
157
+ # necessary typecasting.
158
+ #
159
+ # @example Write the attribute.
160
+ # person.write_attribute(:title, "Mr.")
161
+ #
162
+ # @example Write the attribute (alternate syntax.)
163
+ # person[:title] = "Mr."
164
+ #
165
+ # @param [ String, Symbol ] name The name of the attribute to update.
166
+ # @param [ Object ] value The value to set for the attribute.
167
+ def write_attribute(name, value)
168
+ access = name.to_s
169
+ modify(access, @attributes[access], typed_value_for(access, value))
170
+ end
171
+ alias :[]= :write_attribute
172
+
173
+ # Writes the supplied attributes hash to the document. This will only
174
+ # overwrite existing attributes if they are present in the new +Hash+, all
175
+ # others will be preserved.
176
+ #
177
+ # @example Write the attributes.
178
+ # person.write_attributes(:title => "Mr.")
179
+ #
180
+ # @example Write the attributes (alternate syntax.)
181
+ # person.attributes = { :title => "Mr." }
182
+ #
183
+ # @param [ Hash ] attrs The new attributes to set.
184
+ def write_attributes(attrs = nil)
185
+ process(attrs || {})
186
+ if new_record? && id.blank?
187
+ identify
188
+ end
189
+ end
190
+ alias :attributes= :write_attributes
191
+
192
+ protected
193
+
194
+ # Get the default values for the attributes.
195
+ #
196
+ # @example Get the defaults.
197
+ # person.default_attributes
198
+ #
199
+ # @return [ Hash ] The default values for each field.
200
+ def default_attributes
201
+ default_values = defaults
202
+ default_values.each_pair do |key, val|
203
+ default_values[key] = typed_value_for(key, val.call) if val.respond_to?(:call)
204
+ end
205
+ default_values || {}
206
+ end
207
+
208
+ # Process all the pending relations that needed to wait until ids were set
209
+ # to fire off.
210
+ #
211
+ # @example Process the relations.
212
+ # document.process_relations({ "addressable" => person })
213
+ #
214
+ # @param [ Hash ] pending The pending relation values.
215
+ def process_relations(pending)
216
+ pending.each_pair do |name, value|
217
+ metadata = relations[name]
218
+ if value.is_a?(Hash)
219
+ metadata.nested_builder(value, {}).build(self)
220
+ else
221
+ send("#{name}=", value, :binding => true)
222
+ end
223
+ end
224
+ end
225
+
226
+ # Return true if dynamic field setting is enabled.
227
+ #
228
+ # @example Is a set allowed for this name?
229
+ # person.set_allowed?(:title)
230
+ #
231
+ # @param [ String, Symbol ] key The name of the field.
232
+ #
233
+ # @return [ true, false ] True if allowed, false if not.
234
+ def set_allowed?(key)
235
+ Mongoid.allow_dynamic_fields && !respond_to?("#{key}=")
236
+ end
237
+
238
+ # Return the typecasted value for a field.
239
+ #
240
+ # @example Get the value typecasted.
241
+ # person.typed_value_for(:title, :sir)
242
+ #
243
+ # @param [ String, Symbol ] key The field name.
244
+ # @param [ Object ] value The uncast value.
245
+ #
246
+ # @return [ Object ] The cast value.
247
+ def typed_value_for(key, value)
248
+ fields.has_key?(key) ? fields[key].set(value) : value
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Callbacks
4
+ extend ActiveSupport::Concern
5
+ included do
6
+ extend ActiveModel::Callbacks
7
+ include ActiveModel::Validations::Callbacks
8
+
9
+ define_model_callbacks :initialize, :only => :after
10
+ define_model_callbacks :create, :destroy, :save, :update
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,137 @@
1
+ # encoding: utf-8
2
+ require "mongoid/collections/operations"
3
+ require "mongoid/collections/cyclic_iterator"
4
+ require "mongoid/collections/master"
5
+ require "mongoid/collections/slaves"
6
+
7
+ module Mongoid #:nodoc
8
+
9
+ # This class is the Mongoid wrapper to the Mongo Ruby driver's collection
10
+ # object.
11
+ class Collection
12
+ attr_reader :counter, :name
13
+
14
+ # All write operations should delegate to the master connection. These
15
+ # operations mimic the methods on a Mongo:Collection.
16
+ #
17
+ # @example Delegate the operation.
18
+ # collection.save({ :name => "Al" })
19
+ Collections::Operations::PROXIED.each do |name|
20
+ define_method(name) { |*args| master.send(name, *args) }
21
+ end
22
+
23
+ # Determines where to send the next read query. If the slaves are not
24
+ # defined then send to master. If the read counter is under the configured
25
+ # maximum then return the master. In any other case return the slaves.
26
+ #
27
+ # @example Send the operation to the master or slaves.
28
+ # collection.directed
29
+ #
30
+ # @param [ Hash ] options The operation options.
31
+ #
32
+ # @option options [ true, false ] :cache Should the query cache in memory?
33
+ # @option options [ true, false ] :enslave Send the write to the slave?
34
+ #
35
+ # @return [ Master, Slaves ] The connection to use.
36
+ def directed(options = {})
37
+ options.delete(:cache)
38
+ enslave = options.delete(:enslave) || @klass.enslaved?
39
+ enslave ? master_or_slaves : master
40
+ end
41
+
42
+ # Find documents from the database given a selector and options.
43
+ #
44
+ # @example Find documents in the collection.
45
+ # collection.find({ :test => "value" })
46
+ #
47
+ # @param [ Hash ] selector The query selector.
48
+ # @param [ Hash ] options The options to pass to the db.
49
+ #
50
+ # @return [ Cursor ] The results.
51
+ def find(selector = {}, options = {})
52
+ cursor = Mongoid::Cursor.new(@klass, self, directed(options).find(selector, options))
53
+ if block_given?
54
+ yield cursor; cursor.close
55
+ else
56
+ cursor
57
+ end
58
+ end
59
+
60
+ # Find the first document from the database given a selector and options.
61
+ #
62
+ # @example Find one document.
63
+ # collection.find_one({ :test => "value" })
64
+ #
65
+ # @param [ Hash ] selector The query selector.
66
+ # @param [ Hash ] options The options to pass to the db.
67
+ #
68
+ # @return [ Document, nil ] A matching document or nil if none found.
69
+ def find_one(selector = {}, options = {})
70
+ directed(options).find_one(selector, options)
71
+ end
72
+
73
+ # Initialize a new Mongoid::Collection, setting up the master, slave, and
74
+ # name attributes. Masters will be used for writes, slaves for reads.
75
+ #
76
+ # @example Create the new collection.
77
+ # Collection.new(masters, slaves, "test")
78
+ #
79
+ # @param [ Class ] klass The class the collection is for.
80
+ # @param [ String ] name The name of the collection.
81
+ def initialize(klass, name)
82
+ @klass, @name = klass, name
83
+ end
84
+
85
+ # Perform a map/reduce on the documents.
86
+ #
87
+ # @example Perform the map/reduce.
88
+ # collection.map_reduce(map, reduce)
89
+ #
90
+ # @param [ String ] map The map javascript function.
91
+ # @param [ String ] reduce The reduce javascript function.
92
+ # @param [ Hash ] options The options to pass to the db.
93
+ #
94
+ # @return [ Cursor ] The results.
95
+ def map_reduce(map, reduce, options = {})
96
+ directed(options).map_reduce(map, reduce, options)
97
+ end
98
+ alias :mapreduce :map_reduce
99
+
100
+ # Return the object responsible for writes to the database. This will
101
+ # always return a collection associated with the Master DB.
102
+ #
103
+ # @example Get the master connection.
104
+ # collection.master
105
+ #
106
+ # @return [ Master ] The master connection.
107
+ def master
108
+ db = Mongoid.databases[@klass.database] || Mongoid.master
109
+ @master ||= Collections::Master.new(db, @name)
110
+ end
111
+
112
+ # Return the object responsible for reading documents from the database.
113
+ # This is usually the slave databases, but in their absence the master will
114
+ # handle the task.
115
+ #
116
+ # @example Get the slaves array.
117
+ # collection.slaves
118
+ #
119
+ # @return [ Slaves ] The pool of slave connections.
120
+ def slaves
121
+ slaves = Mongoid.databases["#{@klass.database}_slaves"] || Mongoid.slaves
122
+ @slaves ||= Collections::Slaves.new(slaves, @name)
123
+ end
124
+
125
+ protected
126
+
127
+ # Determine if the read is going to the master or the slaves.
128
+ #
129
+ # @example Use the master or slaves?
130
+ # collection.master_or_slaves
131
+ #
132
+ # @return [ Master, Slaves ] Master if not slaves exist, or slaves.
133
+ def master_or_slaves
134
+ slaves.empty? ? master : slaves
135
+ end
136
+ end
137
+ end