mongoid 2.1.9 → 2.2.0

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