mongoid 2.1.9 → 2.2.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 (78) hide show
  1. data/CHANGELOG.md +281 -0
  2. data/{README.rdoc → README.md} +24 -14
  3. data/Rakefile +1 -1
  4. data/lib/config/locales/bg.yml +5 -0
  5. data/lib/config/locales/de.yml +5 -0
  6. data/lib/config/locales/en-GB.yml +5 -0
  7. data/lib/config/locales/en.yml +5 -0
  8. data/lib/config/locales/es.yml +3 -0
  9. data/lib/config/locales/fr.yml +5 -0
  10. data/lib/config/locales/hi.yml +5 -0
  11. data/lib/config/locales/hu.yml +5 -0
  12. data/lib/config/locales/id.yml +5 -0
  13. data/lib/config/locales/it.yml +5 -0
  14. data/lib/config/locales/ja.yml +5 -0
  15. data/lib/config/locales/kr.yml +5 -0
  16. data/lib/config/locales/nl.yml +5 -0
  17. data/lib/config/locales/pl.yml +5 -0
  18. data/lib/config/locales/pt-BR.yml +5 -0
  19. data/lib/config/locales/pt.yml +5 -0
  20. data/lib/config/locales/ro.yml +5 -0
  21. data/lib/config/locales/ru.yml +5 -0
  22. data/lib/config/locales/sv.yml +5 -0
  23. data/lib/config/locales/vi.yml +5 -0
  24. data/lib/config/locales/zh-CN.yml +5 -0
  25. data/lib/mongoid/atomic.rb +61 -10
  26. data/lib/mongoid/atomic/modifiers.rb +156 -24
  27. data/lib/mongoid/attributes.rb +38 -10
  28. data/lib/mongoid/collection.rb +21 -3
  29. data/lib/mongoid/collections.rb +52 -6
  30. data/lib/mongoid/collections/master.rb +8 -2
  31. data/lib/mongoid/collections/operations.rb +1 -0
  32. data/lib/mongoid/config.rb +5 -2
  33. data/lib/mongoid/config/database.rb +15 -2
  34. data/lib/mongoid/contexts/mongo.rb +3 -0
  35. data/lib/mongoid/criteria.rb +27 -3
  36. data/lib/mongoid/criterion/inclusion.rb +58 -0
  37. data/lib/mongoid/dirty.rb +2 -0
  38. data/lib/mongoid/document.rb +23 -0
  39. data/lib/mongoid/errors.rb +3 -0
  40. data/lib/mongoid/errors/callback.rb +26 -0
  41. data/lib/mongoid/errors/eager_load.rb +25 -0
  42. data/lib/mongoid/errors/invalid_find.rb +19 -0
  43. data/lib/mongoid/extensions.rb +3 -1
  44. data/lib/mongoid/extensions/object_id/conversions.rb +1 -1
  45. data/lib/mongoid/extras.rb +12 -2
  46. data/lib/mongoid/fields.rb +41 -2
  47. data/lib/mongoid/fields/serializable.rb +36 -0
  48. data/lib/mongoid/fields/serializable/foreign_keys/array.rb +13 -14
  49. data/lib/mongoid/fields/serializable/foreign_keys/object.rb +13 -14
  50. data/lib/mongoid/finders.rb +4 -4
  51. data/lib/mongoid/identity_map.rb +33 -20
  52. data/lib/mongoid/keys.rb +24 -1
  53. data/lib/mongoid/nested_attributes.rb +16 -4
  54. data/lib/mongoid/persistence.rb +50 -6
  55. data/lib/mongoid/persistence/operations.rb +1 -4
  56. data/lib/mongoid/persistence/operations/update.rb +3 -1
  57. data/lib/mongoid/relations/builders/nested_attributes/many.rb +27 -44
  58. data/lib/mongoid/relations/builders/referenced/many.rb +2 -1
  59. data/lib/mongoid/relations/builders/referenced/one.rb +1 -1
  60. data/lib/mongoid/relations/cascading.rb +12 -1
  61. data/lib/mongoid/relations/embedded/many.rb +11 -4
  62. data/lib/mongoid/relations/embedded/one.rb +6 -2
  63. data/lib/mongoid/relations/macros.rb +19 -12
  64. data/lib/mongoid/relations/metadata.rb +17 -0
  65. data/lib/mongoid/relations/polymorphic.rb +12 -1
  66. data/lib/mongoid/relations/proxy.rb +24 -0
  67. data/lib/mongoid/relations/referenced/in.rb +20 -0
  68. data/lib/mongoid/relations/referenced/many.rb +30 -6
  69. data/lib/mongoid/relations/referenced/many_to_many.rb +18 -2
  70. data/lib/mongoid/relations/referenced/one.rb +19 -0
  71. data/lib/mongoid/relations/reflections.rb +23 -3
  72. data/lib/mongoid/relations/targets/enumerable.rb +29 -1
  73. data/lib/mongoid/serialization.rb +1 -1
  74. data/lib/mongoid/sharding.rb +12 -2
  75. data/lib/mongoid/threaded.rb +98 -0
  76. data/lib/mongoid/version.rb +1 -1
  77. data/lib/mongoid/versioning.rb +12 -2
  78. metadata +25 -21
@@ -213,6 +213,15 @@ module Mongoid #:nodoc:
213
213
 
214
214
  private
215
215
 
216
+ # Returns the logger
217
+ #
218
+ # @return [ Logger ] The configured logger or a default Logger instance.
219
+ #
220
+ # @since 2.2.0
221
+ def logger
222
+ Mongoid.logger
223
+ end
224
+
216
225
  # Implement this for calls to flatten on array.
217
226
  #
218
227
  # @example Get the document as an array.
@@ -271,9 +280,23 @@ module Mongoid #:nodoc:
271
280
  end
272
281
 
273
282
  # Set the i18n scope to overwrite ActiveModel.
283
+ #
284
+ # @return [ Symbol ] :mongoid
274
285
  def i18n_scope
275
286
  :mongoid
276
287
  end
288
+
289
+ # Returns the logger
290
+ #
291
+ # @example Get the logger.
292
+ # Person.logger
293
+ #
294
+ # @return [ Logger ] The configured logger or a default Logger instance.
295
+ #
296
+ # @since 2.2.0
297
+ def logger
298
+ Mongoid.logger
299
+ end
277
300
  end
278
301
  end
279
302
  end
@@ -1,9 +1,12 @@
1
1
  # encoding: utf-8
2
2
  require "mongoid/errors/mongoid_error"
3
+ require "mongoid/errors/callback"
3
4
  require "mongoid/errors/document_not_found"
5
+ require "mongoid/errors/eager_load"
4
6
  require "mongoid/errors/invalid_collection"
5
7
  require "mongoid/errors/invalid_database"
6
8
  require "mongoid/errors/invalid_field"
9
+ require "mongoid/errors/invalid_find"
7
10
  require "mongoid/errors/invalid_options"
8
11
  require "mongoid/errors/invalid_type"
9
12
  require "mongoid/errors/mixed_relations"
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc
3
+ module Errors #:nodoc
4
+
5
+ # This error is raised when calling #save! or .create! on a model when one
6
+ # of the callbacks returns false.
7
+ class Callback < MongoidError
8
+
9
+ attr_reader :klass, :method
10
+
11
+ # Create the new callbacks error.
12
+ #
13
+ # @example Create the new callbacks error.
14
+ # Callbacks.new(Post, :create!)
15
+ #
16
+ # @param [ Class ] klass The class of the document.
17
+ # @param [ Symbol ] method The name of the method.
18
+ #
19
+ # @since 2.2.0
20
+ def initialize(klass, method)
21
+ @klass, @method = klass, method
22
+ super(translate("callbacks", { :klass => klass, :method => method }))
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc
3
+ module Errors #:nodoc
4
+
5
+ # This error is raised when attempting to eager load a many to many
6
+ # relation.
7
+ class EagerLoad < MongoidError
8
+
9
+ attr_reader :name
10
+
11
+ # Create the new eager load error.
12
+ #
13
+ # @example Create the new eager load error.
14
+ # EagerLoad.new(:preferences)
15
+ #
16
+ # @param [ Symbol ] name The name of the relation.
17
+ #
18
+ # @since 2.2.0
19
+ def initialize(name)
20
+ @name = name
21
+ super(translate("eager_load", { :name => name }))
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc
3
+ module Errors #:nodoc
4
+
5
+ # Raised when invalid arguments are passed to #find.
6
+ class InvalidFind < MongoidError
7
+
8
+ # Create the new invalid find error.
9
+ #
10
+ # @example Create the error.
11
+ # InvalidFind.new
12
+ #
13
+ # @since 2.2.0
14
+ def initialize
15
+ super(translate("calling_document_find_with_nil_is_invalid", {}))
16
+ end
17
+ end
18
+ end
19
+ end
@@ -20,7 +20,9 @@ class Array #:nodoc
20
20
  end
21
21
 
22
22
  class Binary; end #:nodoc:
23
- class Boolean; end #:nodoc:
23
+ unless defined?(Boolean)
24
+ class Boolean; end
25
+ end
24
26
 
25
27
  class FalseClass #:nodoc
26
28
  include Mongoid::Extensions::FalseClass::Equality
@@ -46,7 +46,7 @@ module Mongoid #:nodoc:
46
46
  when ::Hash
47
47
  args.tap do |hash|
48
48
  hash.each_pair do |key, value|
49
- next unless key.to_s =~ /id/
49
+ next unless klass.object_id_field?(key)
50
50
  begin
51
51
  hash[key] = convert(klass, value, reject_blank)
52
52
  rescue BSON::InvalidObjectId; end
@@ -5,13 +5,23 @@ module Mongoid #:nodoc:
5
5
  module Extras
6
6
  extend ActiveSupport::Concern
7
7
 
8
- delegate :cached?, :to => "self.class"
9
-
10
8
  included do
11
9
  class_attribute :cached
12
10
  self.cached = false
13
11
  end
14
12
 
13
+ # Is the class cached?
14
+ #
15
+ # @note Refactored from using delegate for class load performance.
16
+ #
17
+ # @example Is the class cached?
18
+ # person.cached?
19
+ #
20
+ # @return [ true, false ] If the class is cached.
21
+ def cached?
22
+ self.class.cached?
23
+ end
24
+
15
25
  module ClassMethods #:nodoc
16
26
 
17
27
  # Sets caching on for this class. This class level configuration will
@@ -31,8 +31,6 @@ module Mongoid #:nodoc
31
31
  module Fields
32
32
  extend ActiveSupport::Concern
33
33
 
34
- delegate :defaults, :fields, :to => "self.class"
35
-
36
34
  included do
37
35
  field(:_type, :type => String)
38
36
  field(:_id, :type => BSON::ObjectId)
@@ -41,6 +39,30 @@ module Mongoid #:nodoc
41
39
  alias :id= :_id=
42
40
  end
43
41
 
42
+ # Get the default fields.
43
+ #
44
+ # @note Refactored from using delegate for class load performance.
45
+ #
46
+ # @example Get the defaults.
47
+ # model.defaults
48
+ #
49
+ # @return [ Array<String> ] The default field names.
50
+ def defaults
51
+ self.class.defaults
52
+ end
53
+
54
+ # Get the document's fields.
55
+ #
56
+ # @note Refactored from using delegate for class load performance.
57
+ #
58
+ # @example Get the fields.
59
+ # model.fields
60
+ #
61
+ # @return [ Hash ] The fields.
62
+ def fields
63
+ self.class.fields
64
+ end
65
+
44
66
  class << self
45
67
 
46
68
  # Stores the provided block to be run when the option name specified is
@@ -161,6 +183,23 @@ module Mongoid #:nodoc
161
183
  subclass.defaults, subclass.fields = defaults.dup, fields.dup
162
184
  end
163
185
 
186
+ # Is the field with the provided name a BSON::ObjectId?
187
+ #
188
+ # @example Is the field a BSON::ObjectId?
189
+ # Person.object_id_field?(:name)
190
+ #
191
+ # @param [ String, Symbol ] name The name of the field.
192
+ #
193
+ # @return [ true, false ] If the field is a BSON::ObjectId.
194
+ #
195
+ # @since 2.2.0
196
+ def object_id_field?(name)
197
+ field_name = name.to_s
198
+ field_name = "_id" if field_name == "id"
199
+ field = fields[field_name]
200
+ field ? field.object_id_field? : false
201
+ end
202
+
164
203
  # Replace a field with a new type.
165
204
  #
166
205
  # @example Replace the field.
@@ -44,6 +44,18 @@ module Mongoid #:nodoc:
44
44
  end.include?(:deserialize)
45
45
  end
46
46
 
47
+ # Get the constraint from the metadata once.
48
+ #
49
+ # @example Get the constraint.
50
+ # field.constraint
51
+ #
52
+ # @return [ Constraint ] The relation's contraint.
53
+ #
54
+ # @since 2.1.0
55
+ def constraint
56
+ @constraint ||= metadata.constraint
57
+ end
58
+
47
59
  # Deserialize this field from the type stored in MongoDB to the type
48
60
  # defined on the model
49
61
  #
@@ -93,6 +105,30 @@ module Mongoid #:nodoc:
93
105
  @default, @label = options[:default], options[:label]
94
106
  end
95
107
 
108
+ # Get the metadata for the field if its a foreign key.
109
+ #
110
+ # @example Get the metadata.
111
+ # field.metadata
112
+ #
113
+ # @return [ Metadata ] The relation metadata.
114
+ #
115
+ # @since 2.2.0
116
+ def metadata
117
+ @metadata ||= options[:metadata]
118
+ end
119
+
120
+ # Is the field a BSON::ObjectId?
121
+ #
122
+ # @example Is the field a BSON::ObjectId?
123
+ # field.object_id_field?
124
+ #
125
+ # @return [ true, false ] If the field is a BSON::ObjectId.
126
+ #
127
+ # @since 2.2.0
128
+ def object_id_field?
129
+ @object_id_field ||= (type == BSON::ObjectId)
130
+ end
131
+
96
132
  # Serialize the object from the type defined in the model to a MongoDB
97
133
  # compatible object to store.
98
134
  #
@@ -8,6 +8,19 @@ module Mongoid #:nodoc:
8
8
  class Array
9
9
  include Serializable
10
10
 
11
+ # Is the field a BSON::ObjectId?
12
+ #
13
+ # @example Is the field a BSON::ObjectId?
14
+ # field.object_id_field?
15
+ #
16
+ # @return [ true, false ] If the field is a BSON::ObjectId.
17
+ #
18
+ # @since 2.2.0
19
+ def object_id_field?
20
+ @object_id_field ||=
21
+ metadata.polymorphic? ? true : metadata.klass.using_object_ids?
22
+ end
23
+
11
24
  # Serialize the object from the type defined in the model to a MongoDB
12
25
  # compatible object to store.
13
26
  #
@@ -22,20 +35,6 @@ module Mongoid #:nodoc:
22
35
  def serialize(object)
23
36
  object ? constraint.convert(object) : []
24
37
  end
25
-
26
- protected
27
-
28
- # Get the constraint from the metadata once.
29
- #
30
- # @example Get the constraint.
31
- # field.constraint
32
- #
33
- # @return [ Constraint ] The relation's contraint.
34
- #
35
- # @since 2.1.0
36
- def constraint
37
- @constraint ||= options[:metadata].constraint
38
- end
39
38
  end
40
39
  end
41
40
  end
@@ -8,6 +8,19 @@ module Mongoid #:nodoc:
8
8
  class Object
9
9
  include Serializable
10
10
 
11
+ # Is the field a BSON::ObjectId?
12
+ #
13
+ # @example Is the field a BSON::ObjectId?
14
+ # field.object_id_field?
15
+ #
16
+ # @return [ true, false ] If the field is a BSON::ObjectId.
17
+ #
18
+ # @since 2.2.0
19
+ def object_id_field?
20
+ @object_id_field ||=
21
+ metadata.polymorphic? ? true : metadata.klass.using_object_ids?
22
+ end
23
+
11
24
  # Serialize the object from the type defined in the model to a MongoDB
12
25
  # compatible object to store.
13
26
  #
@@ -22,20 +35,6 @@ module Mongoid #:nodoc:
22
35
  def serialize(object)
23
36
  object.blank? ? nil : constraint.convert(object)
24
37
  end
25
-
26
- protected
27
-
28
- # Get the constraint from the metadata once.
29
- #
30
- # @example Get the constraint.
31
- # field.constraint
32
- #
33
- # @return [ Constraint ] The relation's contraint.
34
- #
35
- # @since 2.1.0
36
- def constraint
37
- @constraint ||= options[:metadata].constraint
38
- end
39
38
  end
40
39
  end
41
40
  end
@@ -8,10 +8,10 @@ module Mongoid #:nodoc:
8
8
  # Delegate to the criteria methods that are natural for creating a new
9
9
  # criteria.
10
10
  critera_methods = [ :all_in, :any_in, :any_of, :asc, :ascending, :avg,
11
- :desc, :descending, :excludes, :limit, :max, :min,
12
- :not_in, :only, :order_by, :skip, :sum, :without,
13
- :where, :update, :update_all, :near ]
14
- delegate *(critera_methods.dup << {:to => :criteria})
11
+ :desc, :descending, :excludes, :includes, :limit,
12
+ :max, :min, :not_in, :only, :order_by, :skip, :sum,
13
+ :without, :where, :update, :update_all, :near ]
14
+ delegate *(critera_methods.dup << { :to => :criteria })
15
15
 
16
16
  # Find all documents that match the given conditions.
17
17
  #
@@ -10,31 +10,14 @@ module Mongoid #:nodoc:
10
10
  # map.get(Person, id)
11
11
  #
12
12
  # @param [ Class ] klass The class of the document.
13
- # @param [ Object ] id The document id.
13
+ # @param [ Object, Hash ] idenfier The document id or selector.
14
14
  #
15
15
  # @return [ Document ] The matching document.
16
16
  #
17
17
  # @since 2.1.0
18
- def get(klass, id)
18
+ def get(klass, identifier)
19
19
  return nil unless Mongoid.identity_map_enabled?
20
- documents_for(klass)[id]
21
- end
22
-
23
- # Get a single document that matches the provided criteria.
24
- #
25
- # @example Get the document for the criteria.
26
- # map.match(Person.where(:_id => id))
27
- #
28
- # @param [ Criteria ] criteria The criteria to match.
29
- #
30
- # @return [ Document ] The first matching document.
31
- #
32
- # @since 2.1.0
33
- def match(criteria)
34
- return nil unless Mongoid.identity_map_enabled?
35
- documents_for(criteria.klass).values.detect do |doc|
36
- doc.matches?(criteria.selector)
37
- end
20
+ documents_for(klass)[identifier]
38
21
  end
39
22
 
40
23
  # Remove the document from the identity map.
@@ -67,6 +50,36 @@ module Mongoid #:nodoc:
67
50
  documents_for(document.class)[document.id] = document
68
51
  end
69
52
 
53
+ # Set a document in the identity map for the provided selector.
54
+ #
55
+ # @example Set the document in the map.
56
+ # identity_map.set_selector(document, { :person_id => person.id })
57
+ #
58
+ # @param [ Document ] document The document to set.
59
+ # @param [ Hash ] selector The selector to identify it.
60
+ #
61
+ # @return [ Array<Document> ] The documents.
62
+ #
63
+ # @since 2.2.0
64
+ def set_many(document, selector)
65
+ (documents_for(document.class)[selector] ||= []).push(document)
66
+ end
67
+
68
+ # Set a document in the identity map for the provided selector.
69
+ #
70
+ # @example Set the document in the map.
71
+ # identity_map.set_selector(document, { :person_id => person.id })
72
+ #
73
+ # @param [ Document ] document The document to set.
74
+ # @param [ Hash ] selector The selector to identify it.
75
+ #
76
+ # @return [ Document ] The matching document.
77
+ #
78
+ # @since 2.2.0
79
+ def set_one(document, selector)
80
+ documents_for(document.class)[selector] = document
81
+ end
82
+
70
83
  private
71
84
 
72
85
  # Get the documents in the identity map for a specific class.