mongoid 3.0.0.rc → 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 (82) hide show
  1. data/CHANGELOG.md +109 -4
  2. data/README.md +1 -1
  3. data/Rakefile +1 -0
  4. data/lib/config/locales/en.yml +15 -1
  5. data/lib/mongoid.rb +17 -2
  6. data/lib/mongoid/atomic.rb +54 -7
  7. data/lib/mongoid/attributes.rb +1 -1
  8. data/lib/mongoid/attributes/processing.rb +1 -1
  9. data/lib/mongoid/callbacks.rb +6 -1
  10. data/lib/mongoid/components.rb +2 -1
  11. data/lib/mongoid/config.rb +42 -17
  12. data/lib/mongoid/config/environment.rb +3 -1
  13. data/lib/mongoid/contextual/aggregable/memory.rb +21 -10
  14. data/lib/mongoid/contextual/find_and_modify.rb +14 -12
  15. data/lib/mongoid/contextual/memory.rb +24 -1
  16. data/lib/mongoid/contextual/mongo.rb +148 -29
  17. data/lib/mongoid/copyable.rb +6 -24
  18. data/lib/mongoid/criteria.rb +116 -34
  19. data/lib/mongoid/document.rb +7 -7
  20. data/lib/mongoid/errors.rb +1 -0
  21. data/lib/mongoid/errors/no_metadata.rb +21 -0
  22. data/lib/mongoid/evolvable.rb +19 -0
  23. data/lib/mongoid/extensions.rb +1 -1
  24. data/lib/mongoid/extensions/array.rb +38 -1
  25. data/lib/mongoid/extensions/big_decimal.rb +1 -1
  26. data/lib/mongoid/extensions/date_time.rb +6 -1
  27. data/lib/mongoid/extensions/false_class.rb +12 -0
  28. data/lib/mongoid/extensions/float.rb +12 -0
  29. data/lib/mongoid/extensions/hash.rb +33 -1
  30. data/lib/mongoid/extensions/integer.rb +12 -0
  31. data/lib/mongoid/extensions/object.rb +51 -1
  32. data/lib/mongoid/extensions/object_id.rb +2 -1
  33. data/lib/mongoid/extensions/range.rb +24 -0
  34. data/lib/mongoid/extensions/string.rb +31 -5
  35. data/lib/mongoid/extensions/true_class.rb +12 -0
  36. data/lib/mongoid/fields.rb +20 -21
  37. data/lib/mongoid/fields/foreign_key.rb +23 -7
  38. data/lib/mongoid/fields/standard.rb +3 -3
  39. data/lib/mongoid/finders.rb +3 -7
  40. data/lib/mongoid/hierarchy.rb +19 -1
  41. data/lib/mongoid/identity_map.rb +20 -4
  42. data/lib/mongoid/indexes/validators/options.rb +1 -1
  43. data/lib/mongoid/multi_parameter_attributes.rb +1 -1
  44. data/lib/mongoid/paranoia.rb +3 -32
  45. data/lib/mongoid/persistence.rb +33 -15
  46. data/lib/mongoid/persistence/atomic/operation.rb +1 -1
  47. data/lib/mongoid/persistence/operations.rb +16 -0
  48. data/lib/mongoid/persistence/operations/remove.rb +1 -1
  49. data/lib/mongoid/persistence/operations/upsert.rb +28 -0
  50. data/lib/mongoid/persistence/upsertion.rb +30 -0
  51. data/lib/mongoid/relations.rb +16 -0
  52. data/lib/mongoid/relations/accessors.rb +1 -1
  53. data/lib/mongoid/relations/bindings/referenced/in.rb +1 -1
  54. data/lib/mongoid/relations/builder.rb +1 -1
  55. data/lib/mongoid/relations/builders/nested_attributes/one.rb +1 -1
  56. data/lib/mongoid/relations/builders/referenced/many.rb +1 -1
  57. data/lib/mongoid/relations/cascading.rb +4 -3
  58. data/lib/mongoid/relations/constraint.rb +1 -1
  59. data/lib/mongoid/relations/conversions.rb +1 -1
  60. data/lib/mongoid/relations/embedded/batchable.rb +3 -2
  61. data/lib/mongoid/relations/embedded/many.rb +4 -4
  62. data/lib/mongoid/relations/embedded/one.rb +1 -1
  63. data/lib/mongoid/relations/metadata.rb +67 -23
  64. data/lib/mongoid/relations/nested_builder.rb +2 -2
  65. data/lib/mongoid/relations/proxy.rb +9 -7
  66. data/lib/mongoid/relations/referenced/many.rb +69 -25
  67. data/lib/mongoid/relations/referenced/many_to_many.rb +14 -13
  68. data/lib/mongoid/scoping.rb +0 -17
  69. data/lib/mongoid/serialization.rb +95 -26
  70. data/lib/mongoid/sessions.rb +30 -6
  71. data/lib/mongoid/sessions/factory.rb +2 -0
  72. data/lib/mongoid/threaded.rb +52 -0
  73. data/lib/mongoid/timestamps/created.rb +1 -1
  74. data/lib/mongoid/timestamps/updated.rb +2 -1
  75. data/lib/mongoid/validations/uniqueness.rb +3 -2
  76. data/lib/mongoid/version.rb +1 -1
  77. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +8 -0
  78. data/lib/rails/mongoid.rb +8 -5
  79. metadata +30 -13
  80. data/lib/mongoid/collections/retry.rb +0 -58
  81. data/lib/mongoid/javascript.rb +0 -20
  82. data/lib/mongoid/javascript/functions.yml +0 -63
@@ -3,6 +3,18 @@ module Mongoid
3
3
  module Extensions
4
4
  module FalseClass
5
5
 
6
+ # Get the value of the object as a mongo friendy sort value.
7
+ #
8
+ # @example Get the object as sort criteria.
9
+ # object.__sortable__
10
+ #
11
+ # @return [ Integer ] 0.
12
+ #
13
+ # @since 3.0.0
14
+ def __sortable__
15
+ 0
16
+ end
17
+
6
18
  # Is the passed value a boolean?
7
19
  #
8
20
  # @example Is the value a boolean type?
@@ -15,6 +15,18 @@ module Mongoid
15
15
  ::Time.at(self)
16
16
  end
17
17
 
18
+ # Is the float a number?
19
+ #
20
+ # @example Is the object a number?.
21
+ # object.numeric?
22
+ #
23
+ # @return [ true ] Always true.
24
+ #
25
+ # @since 3.0.0
26
+ def numeric?
27
+ true
28
+ end
29
+
18
30
  module ClassMethods
19
31
 
20
32
  # Turn the object from the ruby type we deal with to a Mongo friendly
@@ -15,6 +15,38 @@ module Mongoid
15
15
  update_values(&:__evolve_object_id__)
16
16
  end
17
17
 
18
+ # Mongoizes each value in the hash to an object id if it is convertable.
19
+ #
20
+ # @example Convert the hash values.
21
+ # { field: id }.__mongoize_object_id__
22
+ #
23
+ # @return [ Hash ] The converted hash.
24
+ #
25
+ # @since 3.0.0
26
+ def __mongoize_object_id__
27
+ update_values(&:__mongoize_object_id__)
28
+ end
29
+
30
+ # Consolidate the key/values in the hash under an atomic $set.
31
+ #
32
+ # @example Consolidate the hash.
33
+ # { name: "Placebo" }.__consolidate__
34
+ #
35
+ # @return [ Hash ] A new consolidated hash.
36
+ #
37
+ # @since 3.0.0
38
+ def __consolidate__
39
+ consolidated = {}
40
+ each_pair do |key, value|
41
+ if key =~ /\$/
42
+ (consolidated[key] ||= {}).merge!(value)
43
+ else
44
+ (consolidated["$set"] ||= {}).merge!(key => value)
45
+ end
46
+ end
47
+ consolidated
48
+ end
49
+
18
50
  # Get the id attribute from this hash, whether it's prefixed with an
19
51
  # underscore or is a symbol.
20
52
  #
@@ -25,7 +57,7 @@ module Mongoid
25
57
  #
26
58
  # @since 2.3.2
27
59
  def extract_id
28
- self["id"] || self["_id"] || self[:id] || self[:_id]
60
+ self["_id"] || self["id"] || self[:id] || self[:_id]
29
61
  end
30
62
 
31
63
  # Turn the object from the ruby type we deal with to a Mongo friendly
@@ -15,6 +15,18 @@ module Mongoid
15
15
  ::Time.at(self)
16
16
  end
17
17
 
18
+ # Is the integer a number?
19
+ #
20
+ # @example Is the object a number?.
21
+ # object.numeric?
22
+ #
23
+ # @return [ true ] Always true.
24
+ #
25
+ # @since 3.0.0
26
+ def numeric?
27
+ true
28
+ end
29
+
18
30
  # Is the object not to be converted to bson on criteria creation?
19
31
  #
20
32
  # @example Is the object unconvertable?
@@ -14,6 +14,19 @@ module Mongoid
14
14
  def __evolve_object_id__
15
15
  self
16
16
  end
17
+ alias :__mongoize_object_id__ :__evolve_object_id__
18
+
19
+ # Convert the object to args for a find query.
20
+ #
21
+ # @example Convert the object to args.
22
+ # object.__find_args__
23
+ #
24
+ # @return [ Object ] self.
25
+ #
26
+ # @since 3.0.0
27
+ def __find_args__
28
+ self
29
+ end
17
30
 
18
31
  # Mongoize a plain object into a time.
19
32
  #
@@ -27,6 +40,18 @@ module Mongoid
27
40
  self
28
41
  end
29
42
 
43
+ # Get the value of the object as a mongo friendy sort value.
44
+ #
45
+ # @example Get the object as sort criteria.
46
+ # object.__sortable__
47
+ #
48
+ # @return [ Object ] self.
49
+ #
50
+ # @since 3.0.0
51
+ def __sortable__
52
+ self
53
+ end
54
+
30
55
  # Do or do not, there is no try. -- Yoda.
31
56
  #
32
57
  # @example Do or do not.
@@ -74,6 +99,30 @@ module Mongoid
74
99
  self
75
100
  end
76
101
 
102
+ # Is the object multi args.
103
+ #
104
+ # @example Is the object multi args?
105
+ # object.multi_arged?
106
+ #
107
+ # @return [ false ] false.
108
+ #
109
+ # @since 3.0.0
110
+ def multi_arged?
111
+ false
112
+ end
113
+
114
+ # Is the object a number?
115
+ #
116
+ # @example Is the object a number?.
117
+ # object.numeric?
118
+ #
119
+ # @return [ false ] Always false.
120
+ #
121
+ # @since 3.0.0
122
+ def numeric?
123
+ false
124
+ end
125
+
77
126
  # Remove the instance variable for the provided name.
78
127
  #
79
128
  # @example Remove the instance variable
@@ -148,7 +197,8 @@ module Mongoid
148
197
  #
149
198
  # @since 3.0.0
150
199
  def __mongoize_fk__(constraint, object)
151
- object.blank? ? nil : constraint.convert(object)
200
+ return nil if !object || object == ""
201
+ constraint.convert(object)
152
202
  end
153
203
 
154
204
  # Convert the object from it's mongo friendly ruby type to this type.
@@ -14,6 +14,7 @@ module Mongoid
14
14
  def __evolve_object_id__
15
15
  self
16
16
  end
17
+ alias :__mongoize_object_id__ :__evolve_object_id__
17
18
 
18
19
  module ClassMethods
19
20
 
@@ -42,7 +43,7 @@ module Mongoid
42
43
  #
43
44
  # @since 3.0.0
44
45
  def mongoize(object)
45
- evolve(object)
46
+ object.__mongoize_object_id__
46
47
  end
47
48
  end
48
49
  end
@@ -3,6 +3,18 @@ module Mongoid
3
3
  module Extensions
4
4
  module Range
5
5
 
6
+ # Get the range as arguments for a find.
7
+ #
8
+ # @example Get the range as find args.
9
+ # range.__find_args__
10
+ #
11
+ # @return [ Array ] The range as an array.
12
+ #
13
+ # @since 3.0.0
14
+ def __find_args__
15
+ to_a
16
+ end
17
+
6
18
  # Turn the object from the ruby type we deal with to a Mongo friendly
7
19
  # type.
8
20
  #
@@ -16,6 +28,18 @@ module Mongoid
16
28
  ::Range.mongoize(self)
17
29
  end
18
30
 
31
+ # Is this a resizable object.
32
+ #
33
+ # @example Is this resizable?
34
+ # range.resizable?
35
+ #
36
+ # @return [ true ] True.
37
+ #
38
+ # @since 3.0.0
39
+ def resizable?
40
+ true
41
+ end
42
+
19
43
  module ClassMethods
20
44
 
21
45
  # Convert the object from it's mongo friendly ruby type to this type.
@@ -11,13 +11,23 @@ module Mongoid
11
11
  # @example Evolve the string.
12
12
  # "test".__evolve_object_id__
13
13
  #
14
- # @return [ String, Moped::BSON::ObjectId, nil ] The evolved string.
14
+ # @return [ String, Moped::BSON::ObjectId ] The evolved string.
15
15
  #
16
16
  # @since 3.0.0
17
17
  def __evolve_object_id__
18
- unless blank?
19
- BSON::ObjectId.legal?(self) ? BSON::ObjectId.from_string(self) : self
20
- end
18
+ convert_to_object_id
19
+ end
20
+
21
+ # Mongoize the string into an object id if possible.
22
+ #
23
+ # @example Evolve the string.
24
+ # "test".__mongoize_object_id__
25
+ #
26
+ # @return [ String, Moped::BSON::ObjectId, nil ] The mongoized string.
27
+ #
28
+ # @since 3.0.0
29
+ def __mongoize_object_id__
30
+ convert_to_object_id unless blank?
21
31
  end
22
32
 
23
33
  # Mongoize the string for storage.
@@ -53,7 +63,7 @@ module Mongoid
53
63
  #
54
64
  # @since 2.3.1
55
65
  def mongoid_id?
56
- self =~ /^(|_)id$/
66
+ self =~ /\A(|_)id$/
57
67
  end
58
68
 
59
69
  # Is the string a number?
@@ -116,6 +126,22 @@ module Mongoid
116
126
  @unconvertable_to_bson ||= false
117
127
  end
118
128
 
129
+ private
130
+
131
+ # If the string is a legal object id, convert it.
132
+ #
133
+ # @api private
134
+ #
135
+ # @example Convert to the object id.
136
+ # string.convert_to_object_id
137
+ #
138
+ # @return [ String, Moped::BSON::ObjectId ] The string or the id.
139
+ #
140
+ # @since 3.0.0
141
+ def convert_to_object_id
142
+ Moped::BSON::ObjectId.legal?(self) ? Moped::BSON::ObjectId.from_string(self) : self
143
+ end
144
+
119
145
  module ClassMethods
120
146
 
121
147
  # Convert the object from it's mongo friendly ruby type to this type.
@@ -3,6 +3,18 @@ module Mongoid
3
3
  module Extensions
4
4
  module TrueClass
5
5
 
6
+ # Get the value of the object as a mongo friendy sort value.
7
+ #
8
+ # @example Get the object as sort criteria.
9
+ # object.__sortable__
10
+ #
11
+ # @return [ Integer ] 1.
12
+ #
13
+ # @since 3.0.0
14
+ def __sortable__
15
+ 1
16
+ end
17
+
6
18
  # Is the passed value a boolean?
7
19
  #
8
20
  # @example Is the value a boolean type?
@@ -24,9 +24,9 @@ module Mongoid
24
24
  field(:_type, default: ->{ self.class.name if hereditary? }, type: String)
25
25
  field(
26
26
  :_id,
27
- default: ->{ BSON::ObjectId.new },
27
+ default: ->{ Moped::BSON::ObjectId.new },
28
28
  pre_processed: true,
29
- type: BSON::ObjectId
29
+ type: Moped::BSON::ObjectId
30
30
  )
31
31
 
32
32
  alias :id :_id
@@ -94,6 +94,21 @@ module Mongoid
94
94
  apply_post_processed_defaults
95
95
  end
96
96
 
97
+ # Returns an array of names for the attributes available on this object.
98
+ #
99
+ # Provides the field names in an ORM-agnostic way. Rails v3.1+ uses this
100
+ # method to automatically wrap params in JSON requests.
101
+ #
102
+ # @example Get the field names
103
+ # docment.attribute_names
104
+ #
105
+ # @return [ Array<String> ] The field names
106
+ #
107
+ # @since 3.0.0
108
+ def attribute_names
109
+ self.class.attribute_names
110
+ end
111
+
97
112
  # Is the document using object ids?
98
113
  #
99
114
  # @note Refactored from using delegate for class load performance.
@@ -148,7 +163,7 @@ module Mongoid
148
163
  # Returns an array of names for the attributes available on this object.
149
164
  #
150
165
  # Provides the field names in an ORM-agnostic way. Rails v3.1+ uses this
151
- # meathod to automatically wrap params in JSON requests.
166
+ # method to automatically wrap params in JSON requests.
152
167
  #
153
168
  # @example Get the field names
154
169
  # Model.attribute_names
@@ -185,22 +200,6 @@ module Mongoid
185
200
  added
186
201
  end
187
202
 
188
- # When inheriting, we want to copy the fields from the parent class and
189
- # set the on the child to start, mimicking the behaviour of the old
190
- # class_inheritable_accessor that was deprecated in Rails edge.
191
- #
192
- # @example Inherit from this class.
193
- # Person.inherited(Doctor)
194
- #
195
- # @param [ Class ] subclass The inheriting class.
196
- #
197
- # @since 2.0.0.rc.6
198
- def inherited(subclass)
199
- super
200
- subclass.fields, subclass.pre_processed_defaults, subclass.post_processed_defaults =
201
- fields.dup, pre_processed_defaults.dup, post_processed_defaults.dup
202
- end
203
-
204
203
  # Replace a field with a new type.
205
204
  #
206
205
  # @example Replace the field.
@@ -217,13 +216,13 @@ module Mongoid
217
216
  add_field(name, fields[name].options.merge(type: type))
218
217
  end
219
218
 
220
- # Convenience method for determining if we are using +BSON::ObjectIds+ as
219
+ # Convenience method for determining if we are using +Moped::BSON::ObjectIds+ as
221
220
  # our id.
222
221
  #
223
222
  # @example Does this class use object ids?
224
223
  # person.using_object_ids?
225
224
  #
226
- # @return [ true, false ] If the class uses BSON::ObjectIds for the id.
225
+ # @return [ true, false ] If the class uses Moped::BSON::ObjectIds for the id.
227
226
  #
228
227
  # @since 1.0.0
229
228
  def using_object_ids?
@@ -62,9 +62,11 @@ module Mongoid
62
62
  #
63
63
  # @since 3.0.0
64
64
  def evolve(object)
65
- return object.id if object.is_a?(Document)
66
- evolved = mongoize(object)
67
- type.resizable? ? evolved.first : evolved
65
+ if object_id_field? || object.is_a?(Document)
66
+ object.__evolve_object_id__
67
+ else
68
+ related_id_field.evolve(object)
69
+ end
68
70
  end
69
71
 
70
72
  # Mongoize the object into the Mongo friendly value.
@@ -81,16 +83,16 @@ module Mongoid
81
83
  if type.resizable? || object_id_field?
82
84
  type.__mongoize_fk__(constraint, object)
83
85
  else
84
- metadata.klass.fields["_id"].mongoize(object)
86
+ related_id_field.mongoize(object)
85
87
  end
86
88
  end
87
89
 
88
- # Is the field a BSON::ObjectId?
90
+ # Is the field a Moped::BSON::ObjectId?
89
91
  #
90
- # @example Is the field a BSON::ObjectId?
92
+ # @example Is the field a Moped::BSON::ObjectId?
91
93
  # field.object_id_field?
92
94
  #
93
- # @return [ true, false ] If the field is a BSON::ObjectId.
95
+ # @return [ true, false ] If the field is a Moped::BSON::ObjectId.
94
96
  #
95
97
  # @since 2.2.0
96
98
  def object_id_field?
@@ -115,6 +117,20 @@ module Mongoid
115
117
  serialize_default(default_val[])
116
118
  end
117
119
 
120
+ # Get the id field of the relation.
121
+ #
122
+ # @api private
123
+ #
124
+ # @example Get the related id field.
125
+ # field.related_id_field
126
+ #
127
+ # @return [ Fields::Standard ] The field.
128
+ #
129
+ # @since 3.0.0
130
+ def related_id_field
131
+ @related_id_field ||= metadata.klass.fields["_id"]
132
+ end
133
+
118
134
  # This is used when default values need to be serialized. Most of the
119
135
  # time just return the object.
120
136
  #