mongoid 2.3.0 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/CHANGELOG.md +56 -2
  2. data/lib/config/locales/bg.yml +2 -0
  3. data/lib/config/locales/de.yml +2 -0
  4. data/lib/config/locales/en-GB.yml +2 -0
  5. data/lib/config/locales/en.yml +2 -0
  6. data/lib/config/locales/es.yml +2 -0
  7. data/lib/config/locales/fr.yml +2 -0
  8. data/lib/config/locales/hi.yml +2 -0
  9. data/lib/config/locales/hu.yml +2 -0
  10. data/lib/config/locales/id.yml +2 -0
  11. data/lib/config/locales/it.yml +2 -0
  12. data/lib/config/locales/ja.yml +2 -0
  13. data/lib/config/locales/kr.yml +2 -0
  14. data/lib/config/locales/nl.yml +2 -0
  15. data/lib/config/locales/pl.yml +2 -0
  16. data/lib/config/locales/pt-BR.yml +2 -0
  17. data/lib/config/locales/pt.yml +2 -0
  18. data/lib/config/locales/ro.yml +2 -0
  19. data/lib/config/locales/ru.yml +2 -0
  20. data/lib/config/locales/sv.yml +2 -0
  21. data/lib/config/locales/vi.yml +2 -0
  22. data/lib/config/locales/zh-CN.yml +2 -0
  23. data/lib/mongoid/contexts/mongo.rb +1 -1
  24. data/lib/mongoid/criterion/inclusion.rb +39 -40
  25. data/lib/mongoid/criterion/selector.rb +5 -0
  26. data/lib/mongoid/dirty.rb +4 -26
  27. data/lib/mongoid/errors.rb +1 -0
  28. data/lib/mongoid/errors/invalid_time.rb +25 -0
  29. data/lib/mongoid/extensions.rb +2 -0
  30. data/lib/mongoid/extensions/hash/criteria_helpers.rb +1 -2
  31. data/lib/mongoid/extensions/object_id/conversions.rb +2 -4
  32. data/lib/mongoid/extensions/string/checks.rb +12 -0
  33. data/lib/mongoid/extensions/symbol/checks.rb +23 -0
  34. data/lib/mongoid/extras.rb +0 -22
  35. data/lib/mongoid/fields.rb +1 -1
  36. data/lib/mongoid/fields/serializable.rb +14 -7
  37. data/lib/mongoid/fields/serializable/timekeeping.rb +6 -2
  38. data/lib/mongoid/named_scope.rb +7 -3
  39. data/lib/mongoid/nested_attributes.rb +0 -12
  40. data/lib/mongoid/paranoia.rb +62 -8
  41. data/lib/mongoid/railties/database.rake +6 -3
  42. data/lib/mongoid/relations.rb +15 -0
  43. data/lib/mongoid/relations/bindings/referenced/in.rb +1 -1
  44. data/lib/mongoid/relations/builders/referenced/in.rb +1 -1
  45. data/lib/mongoid/relations/builders/referenced/one.rb +1 -2
  46. data/lib/mongoid/relations/cascading.rb +0 -12
  47. data/lib/mongoid/relations/embedded/many.rb +28 -9
  48. data/lib/mongoid/relations/macros.rb +8 -18
  49. data/lib/mongoid/relations/metadata.rb +2 -5
  50. data/lib/mongoid/relations/polymorphic.rb +0 -25
  51. data/lib/mongoid/relations/referenced/many.rb +29 -10
  52. data/lib/mongoid/relations/referenced/many_to_many.rb +13 -3
  53. data/lib/mongoid/relations/targets/enumerable.rb +2 -3
  54. data/lib/mongoid/version.rb +1 -1
  55. data/lib/mongoid/versioning.rb +1 -13
  56. metadata +21 -19
@@ -1,13 +1,65 @@
1
1
  # Overview
2
2
 
3
- For instructions on upgrading to newer versions, visit [mongoid.org](http://mongoid.org/docs/upgrading.html).
3
+ For instructions on upgrading to newer versions, visit
4
+ [mongoid.org](http://mongoid.org/docs/upgrading.html).
5
+
6
+ ## 2.4.0 \[ In Development \] \[ Branch: master \]
7
+
8
+ * Ranges can now be passed to #where criteria to create a $gte/$lte query under the
9
+ covers. `Person.where(dob: start_date...end_date)`
10
+
11
+ ## 2.3.1 \[ In Development \] \[ Branch: 2.3.0-stable \]
12
+
13
+ ### Resolved Issues
14
+
15
+ * \#1338 Calling #find on a scope or relation checks that the document in the
16
+ identity map actually matches other scope parameters.
17
+
18
+ * \#1321 HABTM no longer allows duplicate entries or keys, instead of the previous
19
+ inconsistencies.
20
+
21
+ * \#1320 Fixed errors in perf benchmark.
22
+
23
+ * \#1316 Added a separate Rake task "db:mongoid:drop" so Mongoid and AR can coexist.
24
+ (Daniel Vartanov)
25
+
26
+ * \#1311 Fix issue with custom field serialization inheriting from hash.
27
+
28
+ * \#1310 The referenced many enumerable target no longer duplicates loaded and
29
+ added documents when the identity map is enabled.
30
+
31
+ * \#1295 Fixed having multiple includes only execute the eager loading of the first.
32
+
33
+ * \#1287 Fixed max versions limitation with versioning.
34
+
35
+ * \#1277 attribute_will_change! properly flags the attribute even if no change occured.
36
+
37
+ * \#1063 Paranoid documents properly run destroy callbacks on soft destroy.
38
+
39
+ * \#1061 Raise `Mongoid::Errors::InvalidTime` when time serialization fails.
40
+
41
+ * \#1002 Check for legal bson ids when attempting conversion.
42
+
43
+ * \#920 Allow relations to be named target.
44
+
45
+ * \#905 Return normalized class name in metadata if string was defined with a
46
+ prefixed ::.
47
+
48
+ * \#861 accepts_nested_attributes_for is no longer needed to set embedded documents
49
+ via a hash or array of hashes directly.
50
+
51
+ * \#857 Fixed cascading of dependent relations when base document is paranoid.
52
+
53
+ * \#768 Fixed class_attribute definitions module wide.
54
+
55
+ * \#408 Embedded documents can now be soft deleted via `Mongoid::Paranoia`.
4
56
 
5
57
  ## 2.3.0
6
58
 
7
59
  ### New Features
8
60
 
9
61
  * Mongoid now supports basic localized fields, storing them under the covers as a
10
- hash of locale => value pairs. `field :name, localized: true`
62
+ hash of locale => value pairs. `field :name, localize: true`
11
63
 
12
64
  * \#1275 For applications that default safe mode to true, you can now tell a
13
65
  single operation to persist without safe mode via #unsafely:
@@ -88,6 +140,8 @@ For instructions on upgrading to newer versions, visit [mongoid.org](http://mong
88
140
  * Deleting versions created with `Mongoid::Versioning` no longer fires off
89
141
  dependent cascading on relations.
90
142
 
143
+ ## 2.2.3 \[ In Development \] \[ Branch: 2.2.0-stable \]
144
+
91
145
  ## 2.2.2
92
146
 
93
147
  * This release removes the restriction of a dependency on 1.3.x of the mongo
@@ -13,6 +13,8 @@ bg:
13
13
  or polymorphic belongs_to relation."
14
14
  invalid_database:
15
15
  Базата данни трябва да е от тип Mnogo:DB, а не %{name}.
16
+ invalid_time:
17
+ "'%{value}' is not a valid Time."
16
18
  invalid_type:
17
19
  Полето е дефинирано като a(n) %{klass}, но се присвоява %{other}
18
20
  със стойност %{value}.
@@ -13,6 +13,8 @@ de:
13
13
  or polymorphic belongs_to relation."
14
14
  invalid_database:
15
15
  Datenbank sollte eine Mongo::DB sein, nicht %{name}.
16
+ invalid_time:
17
+ "'%{value}' ist keine berechtigte Zeit."
16
18
  invalid_type:
17
19
  Feld wurde als a(n) %{klass} definiert, doch der Wert %{value} vom Typ
18
20
  %{other} wurde übergeben.
@@ -16,6 +16,8 @@ en-GB:
16
16
  invalid_options:
17
17
  "Invalid option :%{invalid} provided to relation :%{name}. Valid options
18
18
  are: %{valid}."
19
+ invalid_time:
20
+ "'%{value}' is not a valid Time."
19
21
  invalid_type:
20
22
  Field was defined as a(n) %{klass}, but received a %{other} with
21
23
  the value %{value}.
@@ -13,6 +13,8 @@ en:
13
13
  or polymorphic belongs_to relation."
14
14
  invalid_database:
15
15
  "Database should be a Mongo::DB, not %{name}."
16
+ invalid_time:
17
+ "'%{value}' is not a valid Time."
16
18
  invalid_options:
17
19
  "Invalid option :%{invalid} provided to relation :%{name}. Valid options
18
20
  are: %{valid}."
@@ -11,6 +11,8 @@ es:
11
11
  or polymorphic belongs_to relation."
12
12
  invalid_database:
13
13
  La base de datos debería ser una instancia de Mongo::DB, en lugar de %{name}.
14
+ invalid_time:
15
+ "'%{value}' is not a valid Time."
14
16
  invalid_type:
15
17
  El campo se definió como %{klass}, pero recibió una instancia de %{other}
16
18
  con el valor %{value}.
@@ -11,6 +11,8 @@ fr:
11
11
  eager_load:
12
12
  "Eager loading :%{name} is not supported due to it being a many-to-many
13
13
  or polymorphic belongs_to relation."
14
+ invalid_time:
15
+ "'%{value}' is not a valid Time."
14
16
  invalid_database:
15
17
  La base de données doit être une Mongo::DB, pas %{name}.
16
18
  invalid_type:
@@ -11,6 +11,8 @@ en:
11
11
  eager_load:
12
12
  "Eager loading :%{name} is not supported due to it being a many-to-many
13
13
  or polymorphic belongs_to relation."
14
+ invalid_time:
15
+ "'%{value}' is not a valid Time."
14
16
  invalid_database:
15
17
  "डेटाबेस Mongo::DB होना चाहिए, %{name} नहीं."
16
18
  invalid_options:
@@ -11,6 +11,8 @@ hu:
11
11
  eager_load:
12
12
  "Eager loading :%{name} is not supported due to it being a many-to-many
13
13
  or polymorphic belongs_to relation."
14
+ invalid_time:
15
+ "'%{value}' is not a valid Time."
14
16
  invalid_database:
15
17
  Az adatbázisnak Mongo::DB-nek kellene lennie, nem %{name}.
16
18
  invalid_type:
@@ -11,6 +11,8 @@ id:
11
11
  eager_load:
12
12
  "Eager loading :%{name} is not supported due to it being a many-to-many
13
13
  or polymorphic belongs_to relation."
14
+ invalid_time:
15
+ "'%{value}' is not a valid Time."
14
16
  invalid_database:
15
17
  Database harus Mongo::DB, bukan %{name}.
16
18
  invalid_type:
@@ -13,6 +13,8 @@ it:
13
13
  or polymorphic belongs_to relation."
14
14
  invalid_database:
15
15
  Il database dovrebbe essere un Mongo::DB, non %{name}.
16
+ invalid_time:
17
+ "'%{value}' is not a valid Time."
16
18
  invalid_type:
17
19
  Il campo è stato definito come %{klass} ma ha ricevuto
18
20
  un %{other} con valore %{value}.
@@ -13,6 +13,8 @@ ja:
13
13
  or polymorphic belongs_to relation."
14
14
  invalid_database:
15
15
  次のDatabaseは利用できませんでした。%{name}
16
+ invalid_time:
17
+ "'%{value}' is not a valid Time."
16
18
  invalid_type:
17
19
  このフィールドは %{klass} で定義されていますが、%{other}に対し %{value} という値が送信されました。
18
20
  invalid_options:
@@ -13,6 +13,8 @@ kr:
13
13
  or polymorphic belongs_to relation."
14
14
  invalid_database:
15
15
  데이타베이스가 Mongo::DB이어야 합니다, %{name}이면 안됩니다.
16
+ invalid_time:
17
+ "'%{value}' is not a valid Time."
16
18
  invalid_type:
17
19
  데이터 필드가 %{klass} 처럼 정의를 내립니다. 하지만 그것은 %{other}를 %{value} 으로 산출되어 받습니다
18
20
  invalid_options:
@@ -13,6 +13,8 @@ nl:
13
13
  or polymorphic belongs_to relation."
14
14
  invalid_database:
15
15
  Database moet een Mongo::DB zijn, niet een %{name}.
16
+ invalid_time:
17
+ "'%{value}' is not a valid Time."
16
18
  invalid_type:
17
19
  Veld was gedefinieerd als een %{klass}, maar ontvangen als %{other} met
18
20
  de waarde %{value}.
@@ -13,6 +13,8 @@ pl:
13
13
  or polymorphic belongs_to relation."
14
14
  invalid_database:
15
15
  Baza danych powinna być typu Mongo::DB, a nie %{name}.
16
+ invalid_time:
17
+ "'%{value}' is not a valid Time."
16
18
  invalid_type:
17
19
  Pole zostało zdefiniowane jako %{klass}, ale otrzymano %{other}
18
20
  z wartością %{value}.
@@ -13,6 +13,8 @@ pt-BR:
13
13
  or polymorphic belongs_to relation."
14
14
  invalid_database:
15
15
  A base de dados deverá ser uma Mongo::DB, em vez de %{name}.
16
+ invalid_time:
17
+ "'%{value}' is not a valid Time."
16
18
  invalid_type:
17
19
  O campo foi definido como %{klass}, mas recebeu uma instância de %{other} com
18
20
  o valor %{value}.
@@ -13,6 +13,8 @@ pt:
13
13
  or polymorphic belongs_to relation."
14
14
  invalid_database:
15
15
  A base de dados deverá ser uma Mongo::DB, em vez de %{name}.
16
+ invalid_time:
17
+ "'%{value}' is not a valid Time."
16
18
  invalid_type:
17
19
  O campo foi definido como %{klass}, mas recebeu uma instância de %{other} com
18
20
  o valor %{value}.
@@ -13,6 +13,8 @@ ro:
13
13
  or polymorphic belongs_to relation."
14
14
  invalid_database:
15
15
  Baza de date ar trebui să fie de tipul Mongo::DB, nu %{name}.
16
+ invalid_time:
17
+ "'%{value}' is not a valid Time."
16
18
  invalid_type:
17
19
  Câmpul a fost definit ca şi un(o) %{klass}, dar valoarea
18
20
  recepţionată %{value} este de clasa %{other}.
@@ -13,6 +13,8 @@ ru:
13
13
  or polymorphic belongs_to relation."
14
14
  invalid_database:
15
15
  База данных должна быть Mongo::DB, а не %{name}.
16
+ invalid_time:
17
+ "'%{value}' is not a valid Time."
16
18
  invalid_type:
17
19
  Поле уже было определено в классе %{klass}, но получено как %{other}
18
20
  со значением %{value}.
@@ -13,6 +13,8 @@ sv:
13
13
  or polymorphic belongs_to relation."
14
14
  invalid_database:
15
15
  Databasen bör vara Mongo::DB, inte %{name}.
16
+ invalid_time:
17
+ "'%{value}' is not a valid Time."
16
18
  invalid_type:
17
19
  Fältet var definerat som %{klass}, men fick %{other} med
18
20
  värdet %{value}.
@@ -13,6 +13,8 @@ vi:
13
13
  or polymorphic belongs_to relation."
14
14
  invalid_database:
15
15
  Cơ sở dữ liệu nên là Mongo::DB, không phải %{name}.
16
+ invalid_time:
17
+ "'%{value}' is not a valid Time."
16
18
  invalid_type:
17
19
  Trường được định nghĩa là một %{klass}, nhưng nhận được %{other} với
18
20
  giá trị %{value}.
@@ -15,6 +15,8 @@ zh-CN:
15
15
  or polymorphic belongs_to relation."
16
16
  invalid_database:
17
17
  数据库应该是Mongo::DB,而不是%{name}.
18
+ invalid_time:
19
+ "'%{value}' is not a valid Time."
18
20
  invalid_type:
19
21
  在类%{klass}中定义了字段,实际值是%{value}的%{other}.
20
22
  invalid_options:
@@ -371,7 +371,7 @@ module Mongoid #:nodoc:
371
371
  :reduce => reduce.gsub("[field]", field)
372
372
  )
373
373
  value = collection.empty? ? nil : collection.first[start.to_s]
374
- value && value.try(:nan?) ? nil : value
374
+ value && value.do_or_do_not(:nan?) ? nil : value
375
375
  end
376
376
 
377
377
  # Filters the field list. If no fields have been supplied, then it will be
@@ -124,12 +124,49 @@ module Mongoid #:nodoc:
124
124
  case type
125
125
  when :first then crit.one
126
126
  when :last then crit.last
127
- when :ids then execute_or_raise(args, crit)
127
+ when :ids then crit.execute_or_raise(args)
128
128
  else
129
129
  crit
130
130
  end
131
131
  end
132
132
 
133
+ # Execute the criteria or raise an error if no documents found.
134
+ #
135
+ # @example Execute or raise
136
+ # criteria.execute_or_raise(id, criteria)
137
+ #
138
+ # @param [ Object ] args The arguments passed.
139
+ # @param [ Criteria ] criteria The criteria to execute.
140
+ #
141
+ # @raise [ Errors::DocumentNotFound ] If nothing returned.
142
+ #
143
+ # @return [ Document, Array<Document> ] The document(s).
144
+ #
145
+ # @since 2.0.0
146
+ def execute_or_raise(args)
147
+ (args[0].is_a?(Array) ? entries : from_map_or_db).tap do |result|
148
+ if Mongoid.raise_not_found_error && !args.flatten.blank?
149
+ raise Errors::DocumentNotFound.new(klass, args) if result._vacant?
150
+ end
151
+ end
152
+ end
153
+
154
+ # Get the document from the identity map, and if not found hit the
155
+ # database.
156
+ #
157
+ # @example Get the document from the map or criteria.
158
+ # criteria.from_map_or_db(criteria)
159
+ #
160
+ # @param [ Criteria ] The cloned criteria.
161
+ #
162
+ # @return [ Document ] The found document.
163
+ #
164
+ # @since 2.2.1
165
+ def from_map_or_db
166
+ doc = IdentityMap.get(klass, extract_id)
167
+ doc && doc.matches?(selector) ? doc : first
168
+ end
169
+
133
170
  # Adds a criterion to the +Criteria+ that specifies values where any can
134
171
  # be matched in order to return results. This is similar to an SQL "IN"
135
172
  # clause. The MongoDB conditional operator that will be used is "$in".
@@ -241,7 +278,7 @@ module Mongoid #:nodoc:
241
278
  # to clean this funkiness up.
242
279
  selector.each_pair do |key, value|
243
280
  if crit.selector.has_key?(key)
244
- if key.to_s =~ /^(|_)id$/
281
+ if key.mongoid_id?
245
282
  if crit.selector.has_key?("$and")
246
283
  crit.selector["$and"] << { key => value }
247
284
  else
@@ -261,44 +298,6 @@ module Mongoid #:nodoc:
261
298
  end
262
299
  end
263
300
  end
264
-
265
- private
266
-
267
- # Execute the criteria or raise an error if no documents found.
268
- #
269
- # @example Execute or raise
270
- # criteria.execute_or_raise(id, criteria)
271
- #
272
- # @param [ Object ] args The arguments passed.
273
- # @param [ Criteria ] criteria The criteria to execute.
274
- #
275
- # @raise [ Errors::DocumentNotFound ] If nothing returned.
276
- #
277
- # @return [ Document, Array<Document> ] The document(s).
278
- #
279
- # @since 2.0.0
280
- def execute_or_raise(args, criteria)
281
- (args[0].is_a?(Array) ? criteria.entries : from_map_or_db(criteria)).tap do |result|
282
- if Mongoid.raise_not_found_error && !args.flatten.blank?
283
- raise Errors::DocumentNotFound.new(klass, args) if result._vacant?
284
- end
285
- end
286
- end
287
-
288
- # Get the document from the identity map, and if not found hit the
289
- # database.
290
- #
291
- # @example Get the document from the map or criteria.
292
- # criteria.from_map_or_db(criteria)
293
- #
294
- # @param [ Criteria ] The cloned criteria.
295
- #
296
- # @return [ Document ] The found document.
297
- #
298
- # @since 2.2.1
299
- def from_map_or_db(criteria)
300
- IdentityMap.get(klass, criteria.extract_id) || criteria.one
301
- end
302
301
  end
303
302
  end
304
303
  end
@@ -112,6 +112,11 @@ module Mongoid #:nodoc:
112
112
  value.map { |v| typecast_value_for(field, v) }
113
113
  when Regexp
114
114
  value
115
+ when Range
116
+ {
117
+ "$gte" => typecast_value_for(field, value.first),
118
+ "$lte" => typecast_value_for(field, value.last)
119
+ }
115
120
  else
116
121
  if field.type == Array
117
122
  Serialization.mongoize(value, value.class)
@@ -4,30 +4,6 @@ module Mongoid #:nodoc:
4
4
  extend ActiveSupport::Concern
5
5
  include ActiveModel::Dirty
6
6
 
7
- # Get the changed values for the document. This is a hash with the name of
8
- # the field as the keys, and the values being an array of previous and
9
- # current pairs.
10
- #
11
- # @example Get the changes.
12
- # document.changes
13
- #
14
- # @note This is overriding the AM::Dirty implementation to handle
15
- # enumerable fields being in the hash when not actually changed.
16
- #
17
- # @return [ Hash ] The changed values.
18
- #
19
- # @since 2.1.0
20
- def changes
21
- {}.tap do |hash|
22
- changed.each do |name|
23
- change = attribute_change(name)
24
- if change
25
- hash[name] = change if change[0] != change[1]
26
- end
27
- end
28
- end
29
- end
30
-
31
7
  # Call this method after save, so the changes can be properly switched.
32
8
  #
33
9
  # This will unset the memoized children array, set new record to
@@ -71,8 +47,10 @@ module Mongoid #:nodoc:
71
47
  def setters
72
48
  {}.tap do |modifications|
73
49
  changes.each_pair do |field, changes|
74
- key = embedded? ? "#{atomic_position}.#{field}" : field
75
- modifications[key] = changes[1]
50
+ if changes
51
+ key = embedded? ? "#{atomic_position}.#{field}" : field
52
+ modifications[key] = changes[1]
53
+ end
76
54
  end
77
55
  end
78
56
  end