mongoid 3.0.0.rc → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
  #