mongoid 2.4.0 → 2.4.12
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.
- data/CHANGELOG.md +329 -1
- data/Rakefile +0 -9
- data/lib/config/locales/bg.yml +1 -0
- data/lib/config/locales/de.yml +1 -0
- data/lib/config/locales/en-GB.yml +1 -0
- data/lib/config/locales/en.yml +1 -0
- data/lib/config/locales/es.yml +1 -0
- data/lib/config/locales/fr.yml +1 -0
- data/lib/config/locales/hi.yml +1 -0
- data/lib/config/locales/hu.yml +1 -0
- data/lib/config/locales/id.yml +1 -0
- data/lib/config/locales/it.yml +1 -0
- data/lib/config/locales/ja.yml +1 -0
- data/lib/config/locales/kr.yml +1 -0
- data/lib/config/locales/nl.yml +1 -0
- data/lib/config/locales/pl.yml +1 -0
- data/lib/config/locales/pt-BR.yml +1 -0
- data/lib/config/locales/pt.yml +1 -0
- data/lib/config/locales/ro.yml +1 -0
- data/lib/config/locales/ru.yml +1 -0
- data/lib/config/locales/sv.yml +1 -0
- data/lib/config/locales/vi.yml +1 -0
- data/lib/config/locales/zh-CN.yml +1 -0
- data/lib/mongoid/atomic/modifiers.rb +56 -15
- data/lib/mongoid/atomic.rb +14 -8
- data/lib/mongoid/attributes.rb +1 -1
- data/lib/mongoid/callbacks.rb +3 -3
- data/lib/mongoid/collection.rb +5 -1
- data/lib/mongoid/collections/retry.rb +2 -1
- data/lib/mongoid/components.rb +2 -1
- data/lib/mongoid/config/database.rb +4 -7
- data/lib/mongoid/config/environment.rb +4 -2
- data/lib/mongoid/config/replset_database.rb +3 -5
- data/lib/mongoid/config.rb +18 -0
- data/lib/mongoid/contexts/enumerable.rb +26 -1
- data/lib/mongoid/contexts/mongo.rb +62 -14
- data/lib/mongoid/copyable.rb +38 -8
- data/lib/mongoid/criteria.rb +1 -0
- data/lib/mongoid/criterion/exclusion.rb +3 -1
- data/lib/mongoid/criterion/inclusion.rb +2 -2
- data/lib/mongoid/criterion/optional.rb +2 -2
- data/lib/mongoid/criterion/selector.rb +25 -4
- data/lib/mongoid/cursor.rb +4 -2
- data/lib/mongoid/dirty.rb +61 -18
- data/lib/mongoid/document.rb +6 -2
- data/lib/mongoid/extensions/hash/criteria_helpers.rb +3 -1
- data/lib/mongoid/extensions/string/inflections.rb +1 -1
- data/lib/mongoid/factory.rb +3 -3
- data/lib/mongoid/fields/internal/array.rb +4 -9
- data/lib/mongoid/fields/internal/big_decimal.rb +7 -1
- data/lib/mongoid/fields/internal/date_time.rb +1 -1
- data/lib/mongoid/fields/internal/false_class.rb +10 -0
- data/lib/mongoid/fields/internal/foreign_keys/array.rb +22 -8
- data/lib/mongoid/fields/internal/set.rb +1 -1
- data/lib/mongoid/fields/internal/timekeeping.rb +2 -1
- data/lib/mongoid/fields/internal/true_class.rb +10 -0
- data/lib/mongoid/fields/mappings.rb +14 -13
- data/lib/mongoid/fields/serializable.rb +41 -3
- data/lib/mongoid/fields.rb +154 -26
- data/lib/mongoid/hierarchy.rb +6 -1
- data/lib/mongoid/identity_map.rb +15 -0
- data/lib/mongoid/logger.rb +7 -1
- data/lib/mongoid/matchers/all.rb +8 -1
- data/lib/mongoid/matchers/in.rb +8 -1
- data/lib/mongoid/matchers/strategies.rb +6 -2
- data/lib/mongoid/multi_database.rb +5 -0
- data/lib/mongoid/named_scope.rb +17 -1
- data/lib/mongoid/nested_attributes.rb +1 -1
- data/lib/mongoid/observer.rb +7 -0
- data/lib/mongoid/persistence/insertion.rb +2 -1
- data/lib/mongoid/persistence/operations/update.rb +0 -9
- data/lib/mongoid/persistence.rb +5 -5
- data/lib/mongoid/railtie.rb +22 -4
- data/lib/mongoid/relations/bindings/referenced/in.rb +31 -11
- data/lib/mongoid/relations/bindings/referenced/many.rb +8 -8
- data/lib/mongoid/relations/bindings/referenced/one.rb +8 -8
- data/lib/mongoid/relations/builders/nested_attributes/many.rb +3 -1
- data/lib/mongoid/relations/cascading/delete.rb +29 -2
- data/lib/mongoid/relations/cascading/destroy.rb +18 -1
- data/lib/mongoid/relations/cascading/nullify.rb +18 -1
- data/lib/mongoid/relations/cascading.rb +0 -1
- data/lib/mongoid/relations/embedded/atomic.rb +3 -3
- data/lib/mongoid/relations/embedded/many.rb +58 -26
- data/lib/mongoid/relations/embedded/one.rb +1 -1
- data/lib/mongoid/relations/metadata.rb +33 -1
- data/lib/mongoid/relations/one.rb +12 -0
- data/lib/mongoid/relations/proxy.rb +6 -3
- data/lib/mongoid/relations/referenced/many.rb +14 -9
- data/lib/mongoid/relations/referenced/many_to_many.rb +3 -4
- data/lib/mongoid/relations/targets/enumerable.rb +9 -3
- data/lib/mongoid/relations.rb +3 -1
- data/lib/mongoid/serialization.rb +18 -6
- data/lib/mongoid/state.rb +1 -1
- data/lib/mongoid/threaded.rb +26 -0
- data/lib/mongoid/timestamps/updated.rb +1 -1
- data/lib/mongoid/validations/format.rb +20 -0
- data/lib/mongoid/validations/length.rb +20 -0
- data/lib/mongoid/validations/localizable.rb +30 -0
- data/lib/mongoid/validations/presence.rb +6 -2
- data/lib/mongoid/validations/uniqueness.rb +162 -30
- data/lib/mongoid/validations.rb +54 -2
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid/versioning.rb +12 -3
- data/lib/mongoid.rb +1 -0
- data/lib/rails/mongoid.rb +18 -12
- metadata +58 -41
- data/lib/mongoid/relations/cascading/strategy.rb +0 -26
|
@@ -16,11 +16,13 @@ module Mongoid #:nodoc:
|
|
|
16
16
|
# @since 1.0.0
|
|
17
17
|
def expand_complex_criteria
|
|
18
18
|
{}.tap do |hsh|
|
|
19
|
-
each_pair do |k,v|
|
|
19
|
+
each_pair do |k, v|
|
|
20
20
|
if k.respond_to?(:key) && k.respond_to?(:to_mongo_query)
|
|
21
21
|
hsh[k.key] ||= {}
|
|
22
|
+
v = v.expand_complex_criteria if v.is_a?(::Hash)
|
|
22
23
|
hsh[k.key].merge!(k.to_mongo_query(v))
|
|
23
24
|
else
|
|
25
|
+
v.map!{|e| e.is_a?(::Hash) ? e.expand_complex_criteria : e } if v.is_a?(::Array)
|
|
24
26
|
hsh[k] = v
|
|
25
27
|
end
|
|
26
28
|
end
|
data/lib/mongoid/factory.rb
CHANGED
|
@@ -15,7 +15,7 @@ module Mongoid #:nodoc:
|
|
|
15
15
|
# @param [ Hash ] optiosn The mass assignment scoping options.
|
|
16
16
|
#
|
|
17
17
|
# @return [ Document ] The instantiated document.
|
|
18
|
-
def build(klass, attributes =
|
|
18
|
+
def build(klass, attributes = nil, options = {})
|
|
19
19
|
type = (attributes || {})["_type"]
|
|
20
20
|
if type && klass._types.include?(type)
|
|
21
21
|
type.constantize.new(attributes, options)
|
|
@@ -34,8 +34,8 @@ module Mongoid #:nodoc:
|
|
|
34
34
|
# @param [ Hash ] attributes The document attributes.
|
|
35
35
|
#
|
|
36
36
|
# @return [ Document ] The instantiated document.
|
|
37
|
-
def from_db(klass, attributes =
|
|
38
|
-
type = attributes["_type"]
|
|
37
|
+
def from_db(klass, attributes = nil)
|
|
38
|
+
type = (attributes || {})["_type"]
|
|
39
39
|
if type.blank?
|
|
40
40
|
klass.instantiate(attributes)
|
|
41
41
|
else
|
|
@@ -13,20 +13,15 @@ module Mongoid #:nodoc:
|
|
|
13
13
|
# field.add_atomic_changes(doc, "key", {}, [], [])
|
|
14
14
|
#
|
|
15
15
|
# @param [ Document ] document The document to add to.
|
|
16
|
-
# @param [ String ]
|
|
16
|
+
# @param [ String ] name The name of the field.
|
|
17
|
+
# @param [ String ] key The atomic location of the field.
|
|
17
18
|
# @param [ Hash ] mods The current modifications.
|
|
18
19
|
# @param [ Array ] new The new elements to add.
|
|
19
20
|
# @param [ Array ] old The old elements getting removed.
|
|
20
21
|
#
|
|
21
22
|
# @since 2.4.0
|
|
22
|
-
def add_atomic_changes(document, key, mods, new, old)
|
|
23
|
-
|
|
24
|
-
mods[key] = document.attributes[key]
|
|
25
|
-
elsif new.any?
|
|
26
|
-
document.atomic_array_pushes[key] = new
|
|
27
|
-
elsif old.any?
|
|
28
|
-
document.atomic_array_pulls[key] = old
|
|
29
|
-
end
|
|
23
|
+
def add_atomic_changes(document, name, key, mods, new, old)
|
|
24
|
+
mods[key] = new
|
|
30
25
|
end
|
|
31
26
|
|
|
32
27
|
# Array fields are resizable.
|
|
@@ -19,7 +19,13 @@ module Mongoid #:nodoc:
|
|
|
19
19
|
#
|
|
20
20
|
# @since 2.1.0
|
|
21
21
|
def deserialize(object)
|
|
22
|
-
|
|
22
|
+
return object unless object
|
|
23
|
+
begin
|
|
24
|
+
Float(object)
|
|
25
|
+
::BigDecimal.new(object)
|
|
26
|
+
rescue ArgumentError, TypeError
|
|
27
|
+
object
|
|
28
|
+
end
|
|
23
29
|
end
|
|
24
30
|
|
|
25
31
|
# Special case to serialize the object.
|
|
@@ -13,20 +13,34 @@ module Mongoid #:nodoc:
|
|
|
13
13
|
# @example Add the atomic changes.
|
|
14
14
|
# field.add_atomic_changes(doc, "key", {}, [], [])
|
|
15
15
|
#
|
|
16
|
+
# @todo: Durran: Refactor, big time.
|
|
17
|
+
#
|
|
16
18
|
# @param [ Document ] document The document to add to.
|
|
17
|
-
# @param [ String ]
|
|
19
|
+
# @param [ String ] name The name of the field.
|
|
20
|
+
# @param [ String ] key The atomic location of the field.
|
|
18
21
|
# @param [ Hash ] mods The current modifications.
|
|
19
22
|
# @param [ Array ] new The new elements to add.
|
|
20
23
|
# @param [ Array ] old The old elements getting removed.
|
|
21
24
|
#
|
|
22
25
|
# @since 2.4.0
|
|
23
|
-
def add_atomic_changes(document, key, mods,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
def add_atomic_changes(document, name, key, mods, new_elements, old_elements)
|
|
27
|
+
old = (old_elements || [])
|
|
28
|
+
new = (new_elements || [])
|
|
29
|
+
if new.length > old.length
|
|
30
|
+
if new.first(old.length) == old
|
|
31
|
+
document.atomic_array_add_to_sets[key] = new.drop(old.length)
|
|
32
|
+
else
|
|
33
|
+
mods[key] = document.attributes[name]
|
|
34
|
+
end
|
|
35
|
+
elsif new.length < old.length
|
|
36
|
+
pulls = old - new
|
|
37
|
+
if new == old - pulls
|
|
38
|
+
document.atomic_array_pulls[key] = pulls
|
|
39
|
+
else
|
|
40
|
+
mods[key] = document.attributes[name]
|
|
41
|
+
end
|
|
42
|
+
elsif new != old
|
|
43
|
+
mods[key] = document.attributes[name]
|
|
30
44
|
end
|
|
31
45
|
end
|
|
32
46
|
|
|
@@ -32,7 +32,7 @@ module Mongoid #:nodoc:
|
|
|
32
32
|
return nil if object.blank?
|
|
33
33
|
object = object.getlocal unless Mongoid::Config.use_utc?
|
|
34
34
|
if Mongoid::Config.use_activesupport_time_zone?
|
|
35
|
-
time_zone = Mongoid::Config.use_utc? ?
|
|
35
|
+
time_zone = Mongoid::Config.use_utc? ? "UTC" : ::Time.zone
|
|
36
36
|
object = object.in_time_zone(time_zone)
|
|
37
37
|
end
|
|
38
38
|
object
|
|
@@ -90,6 +90,7 @@ module Mongoid #:nodoc:
|
|
|
90
90
|
when ::String
|
|
91
91
|
time.parse(value)
|
|
92
92
|
when ::DateTime
|
|
93
|
+
return value if value.utc? && Mongoid.use_utc?
|
|
93
94
|
time.local(value.year, value.month, value.day, value.hour, value.min, value.sec)
|
|
94
95
|
when ::Date
|
|
95
96
|
time.local(value.year, value.month, value.day)
|
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
module Mongoid #:nodoc
|
|
3
3
|
module Fields #:nodoc:
|
|
4
4
|
|
|
5
|
+
module Internal #:nodoc:
|
|
6
|
+
end
|
|
7
|
+
|
|
5
8
|
# This module maps classes used in field type definitions to the custom
|
|
6
9
|
# definable field in Mongoid.
|
|
7
10
|
module Mappings
|
|
8
11
|
extend self
|
|
9
12
|
|
|
10
|
-
MODULE = "Mongoid::Fields::Internal"
|
|
11
|
-
|
|
12
13
|
# Get the custom field type for the provided class used in the field
|
|
13
14
|
# definition.
|
|
14
15
|
#
|
|
@@ -21,21 +22,21 @@ module Mongoid #:nodoc
|
|
|
21
22
|
#
|
|
22
23
|
# @since 2.1.0
|
|
23
24
|
def for(klass, foreign_key = false)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
modules = "
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
if klass.nil?
|
|
26
|
+
Internal::Object
|
|
27
|
+
elsif foreign_key
|
|
28
|
+
Internal::ForeignKeys.const_get(klass.to_s)
|
|
29
|
+
else
|
|
30
|
+
modules = "BSON::|ActiveSupport::"
|
|
31
|
+
match = klass.to_s.match(Regexp.new("^(#{ modules })?(\\w+)$"))
|
|
32
|
+
if match and Internal.const_defined?(match[2])
|
|
33
|
+
Internal.const_get(match[2])
|
|
32
34
|
else
|
|
33
|
-
klass
|
|
35
|
+
klass
|
|
34
36
|
end
|
|
35
|
-
rescue NameError
|
|
36
|
-
klass
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
|
+
|
|
39
40
|
end
|
|
40
41
|
end
|
|
41
42
|
end
|
|
@@ -74,10 +74,10 @@ module Mongoid #:nodoc:
|
|
|
74
74
|
#
|
|
75
75
|
# @since 2.1.8
|
|
76
76
|
def eval_default(doc)
|
|
77
|
-
if
|
|
78
|
-
|
|
77
|
+
if fields = Threaded.selection
|
|
78
|
+
evaluated_default(doc) if included?(fields)
|
|
79
79
|
else
|
|
80
|
-
|
|
80
|
+
evaluated_default(doc)
|
|
81
81
|
end
|
|
82
82
|
end
|
|
83
83
|
|
|
@@ -188,6 +188,44 @@ module Mongoid #:nodoc:
|
|
|
188
188
|
@versioned ||= (options[:versioned].nil? ? true : options[:versioned])
|
|
189
189
|
end
|
|
190
190
|
|
|
191
|
+
private
|
|
192
|
+
|
|
193
|
+
# Is the field included in the fields that were returned from the
|
|
194
|
+
# database? We can apply the default if:
|
|
195
|
+
# 1. The field is included in an only limitation (field: 1)
|
|
196
|
+
# 2. The field is not excluded in a without limitation (field: 0)
|
|
197
|
+
#
|
|
198
|
+
# @example Is the field included?
|
|
199
|
+
# field.included?(fields)
|
|
200
|
+
#
|
|
201
|
+
# @param [ Hash ] fields The field limitations.
|
|
202
|
+
#
|
|
203
|
+
# @return [ true, false ] If the field was included.
|
|
204
|
+
#
|
|
205
|
+
# @since 2.4.4
|
|
206
|
+
def included?(fields)
|
|
207
|
+
(fields.values.first == 1 && fields[name.to_sym] == 1) ||
|
|
208
|
+
(fields.values.first == 0 && !fields.has_key?(name.to_sym))
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# Get the evaluated default.
|
|
212
|
+
#
|
|
213
|
+
# @example Get the evaluated default.
|
|
214
|
+
# field.evaluated_default.
|
|
215
|
+
#
|
|
216
|
+
# @param [ Document ] doc The doc being applied to.
|
|
217
|
+
#
|
|
218
|
+
# @return [ Object ] The default value.
|
|
219
|
+
#
|
|
220
|
+
# @since 2.4.4
|
|
221
|
+
def evaluated_default(doc)
|
|
222
|
+
if default_val.respond_to?(:call)
|
|
223
|
+
serialize(doc.instance_exec(&default_val))
|
|
224
|
+
else
|
|
225
|
+
serialize(default_val.duplicable? ? default_val.dup : default_val)
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
191
229
|
module ClassMethods #:nodoc:
|
|
192
230
|
|
|
193
231
|
# Create the new field with a name and optional additional options.
|
data/lib/mongoid/fields.rb
CHANGED
|
@@ -8,6 +8,7 @@ require "mongoid/fields/internal/binary"
|
|
|
8
8
|
require "mongoid/fields/internal/boolean"
|
|
9
9
|
require "mongoid/fields/internal/date"
|
|
10
10
|
require "mongoid/fields/internal/date_time"
|
|
11
|
+
require "mongoid/fields/internal/false_class"
|
|
11
12
|
require "mongoid/fields/internal/float"
|
|
12
13
|
require "mongoid/fields/internal/hash"
|
|
13
14
|
require "mongoid/fields/internal/integer"
|
|
@@ -23,6 +24,7 @@ require "mongoid/fields/internal/string"
|
|
|
23
24
|
require "mongoid/fields/internal/symbol"
|
|
24
25
|
require "mongoid/fields/internal/time"
|
|
25
26
|
require "mongoid/fields/internal/time_with_zone"
|
|
27
|
+
require "mongoid/fields/internal/true_class"
|
|
26
28
|
require "mongoid/fields/internal/foreign_keys/array"
|
|
27
29
|
require "mongoid/fields/internal/foreign_keys/object"
|
|
28
30
|
|
|
@@ -90,8 +92,10 @@ module Mongoid #:nodoc
|
|
|
90
92
|
unless attributes.has_key?(name)
|
|
91
93
|
if field = fields[name]
|
|
92
94
|
default = field.eval_default(self)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
unless default.nil?
|
|
96
|
+
attribute_will_change!(name)
|
|
97
|
+
attributes[name] = default
|
|
98
|
+
end
|
|
95
99
|
end
|
|
96
100
|
end
|
|
97
101
|
end
|
|
@@ -276,14 +280,15 @@ module Mongoid #:nodoc
|
|
|
276
280
|
def add_field(name, options = {})
|
|
277
281
|
aliased = options[:as]
|
|
278
282
|
aliased_fields[aliased.to_s] = name if aliased
|
|
279
|
-
meth = aliased || name
|
|
280
283
|
type = options[:localize] ? Fields::Internal::Localized : options[:type]
|
|
281
284
|
Mappings.for(type, options[:identity]).instantiate(name, options).tap do |field|
|
|
282
285
|
fields[name] = field
|
|
283
286
|
add_defaults(field)
|
|
284
|
-
create_accessors(name,
|
|
287
|
+
create_accessors(name, name, options)
|
|
288
|
+
create_accessors(name, aliased, options) if aliased
|
|
285
289
|
process_options(field)
|
|
286
|
-
create_dirty_methods(name)
|
|
290
|
+
create_dirty_methods(name, name)
|
|
291
|
+
create_dirty_methods(name, aliased) if aliased
|
|
287
292
|
end
|
|
288
293
|
end
|
|
289
294
|
|
|
@@ -337,43 +342,164 @@ module Mongoid #:nodoc
|
|
|
337
342
|
# @param [ Symbol ] name The name of the field.
|
|
338
343
|
# @param [ Symbol ] meth The name of the accessor.
|
|
339
344
|
# @param [ Hash ] options The options.
|
|
345
|
+
#
|
|
346
|
+
# @since 2.0.0
|
|
340
347
|
def create_accessors(name, meth, options = {})
|
|
341
348
|
field = fields[name]
|
|
349
|
+
|
|
350
|
+
create_field_getter(name, meth, field)
|
|
351
|
+
create_field_setter(name, meth)
|
|
352
|
+
create_field_check(name, meth)
|
|
353
|
+
|
|
354
|
+
if options[:localize]
|
|
355
|
+
create_translations_getter(name, meth)
|
|
356
|
+
create_translations_setter(name, meth)
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# Create the getter method for the provided field.
|
|
361
|
+
#
|
|
362
|
+
# @example Create the getter.
|
|
363
|
+
# Model.create_field_getter("name", "name", field)
|
|
364
|
+
#
|
|
365
|
+
# @param [ String ] name The name of the attribute.
|
|
366
|
+
# @param [ String ] meth The name of the method.
|
|
367
|
+
# @param [ Field ] field The field.
|
|
368
|
+
#
|
|
369
|
+
# @since 2.4.0
|
|
370
|
+
def create_field_getter(name, meth, field)
|
|
342
371
|
generated_methods.module_eval do
|
|
343
|
-
if
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
fields[
|
|
372
|
+
if meth =~ /\W/
|
|
373
|
+
if field.cast_on_read?
|
|
374
|
+
define_method(meth) do
|
|
375
|
+
fields[name].deserialize(read_attribute(name))
|
|
347
376
|
end
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
def #{meth}
|
|
352
|
-
read_attribute(#{name.inspect}).tap do |value|
|
|
377
|
+
else
|
|
378
|
+
define_method(meth) do
|
|
379
|
+
read_attribute(name).tap do |value|
|
|
353
380
|
if value.is_a?(Array) || value.is_a?(Hash)
|
|
354
|
-
attribute_will_change!(
|
|
381
|
+
attribute_will_change!(name)
|
|
355
382
|
end
|
|
356
383
|
end
|
|
357
384
|
end
|
|
358
|
-
|
|
385
|
+
end
|
|
386
|
+
else
|
|
387
|
+
if field.cast_on_read?
|
|
388
|
+
class_eval <<-EOM
|
|
389
|
+
def #{meth}
|
|
390
|
+
fields[#{name.inspect}].deserialize(read_attribute(#{name.inspect}))
|
|
391
|
+
end
|
|
392
|
+
EOM
|
|
393
|
+
else
|
|
394
|
+
class_eval <<-EOM
|
|
395
|
+
def #{meth}
|
|
396
|
+
read_attribute(#{name.inspect}).tap do |value|
|
|
397
|
+
if value.is_a?(Array) || value.is_a?(Hash)
|
|
398
|
+
attribute_will_change!(#{name.inspect})
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
EOM
|
|
403
|
+
end
|
|
359
404
|
end
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
# Create the setter method for the provided field.
|
|
409
|
+
#
|
|
410
|
+
# @example Create the setter.
|
|
411
|
+
# Model.create_field_setter("name", "name")
|
|
412
|
+
#
|
|
413
|
+
# @param [ String ] name The name of the attribute.
|
|
414
|
+
# @param [ String ] meth The name of the method.
|
|
415
|
+
#
|
|
416
|
+
# @since 2.4.0
|
|
417
|
+
def create_field_setter(name, meth)
|
|
418
|
+
generated_methods.module_eval do
|
|
419
|
+
if meth =~ /\W/
|
|
420
|
+
define_method(meth) do |value|
|
|
421
|
+
write_attribute(name, value)
|
|
363
422
|
end
|
|
423
|
+
else
|
|
424
|
+
class_eval <<-EOM
|
|
425
|
+
def #{meth}=(value)
|
|
426
|
+
write_attribute(#{name.inspect}, value)
|
|
427
|
+
end
|
|
428
|
+
EOM
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
end
|
|
364
432
|
|
|
365
|
-
|
|
366
|
-
|
|
433
|
+
# Create the check method for the provided field.
|
|
434
|
+
#
|
|
435
|
+
# @example Create the check.
|
|
436
|
+
# Model.create_field_check("name", "name")
|
|
437
|
+
#
|
|
438
|
+
# @param [ String ] name The name of the attribute.
|
|
439
|
+
# @param [ String ] meth The name of the method.
|
|
440
|
+
#
|
|
441
|
+
# @since 2.4.0
|
|
442
|
+
def create_field_check(name, meth)
|
|
443
|
+
generated_methods.module_eval do
|
|
444
|
+
if meth =~ /\W/
|
|
445
|
+
define_method("#{meth}?") do
|
|
446
|
+
attr = read_attribute(name)
|
|
367
447
|
attr == true || attr.present?
|
|
368
448
|
end
|
|
369
|
-
|
|
449
|
+
else
|
|
450
|
+
class_eval <<-EOM
|
|
451
|
+
def #{meth}?
|
|
452
|
+
attr = read_attribute(#{name.inspect})
|
|
453
|
+
attr == true || attr.present?
|
|
454
|
+
end
|
|
455
|
+
EOM
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
end
|
|
370
459
|
|
|
371
|
-
|
|
460
|
+
# Create the translation getter method for the provided field.
|
|
461
|
+
#
|
|
462
|
+
# @example Create the translation getter.
|
|
463
|
+
# Model.create_translations_getter("name", "name")
|
|
464
|
+
#
|
|
465
|
+
# @param [ String ] name The name of the attribute.
|
|
466
|
+
# @param [ String ] meth The name of the method.
|
|
467
|
+
#
|
|
468
|
+
# @since 2.4.0
|
|
469
|
+
def create_translations_getter(name, meth)
|
|
470
|
+
generated_methods.module_eval do
|
|
471
|
+
if meth =~ /\W/
|
|
472
|
+
define_method("#{meth}_translations") do
|
|
473
|
+
attributes[name]
|
|
474
|
+
end
|
|
475
|
+
else
|
|
372
476
|
class_eval <<-EOM
|
|
373
477
|
def #{meth}_translations
|
|
374
478
|
attributes[#{name.inspect}]
|
|
375
479
|
end
|
|
480
|
+
EOM
|
|
481
|
+
end
|
|
482
|
+
end
|
|
483
|
+
end
|
|
376
484
|
|
|
485
|
+
# Create the translation setter method for the provided field.
|
|
486
|
+
#
|
|
487
|
+
# @example Create the translation setter.
|
|
488
|
+
# Model.create_translations_setter("name", "name")
|
|
489
|
+
#
|
|
490
|
+
# @param [ String ] name The name of the attribute.
|
|
491
|
+
# @param [ String ] meth The name of the method.
|
|
492
|
+
#
|
|
493
|
+
# @since 2.4.0
|
|
494
|
+
def create_translations_setter(name, meth)
|
|
495
|
+
generated_methods.module_eval do
|
|
496
|
+
if meth =~ /\W/
|
|
497
|
+
define_method("#{meth}_translations=") do |value|
|
|
498
|
+
attribute_will_change!(name)
|
|
499
|
+
attributes[name] = value
|
|
500
|
+
end
|
|
501
|
+
else
|
|
502
|
+
class_eval <<-EOM
|
|
377
503
|
def #{meth}_translations=(value)
|
|
378
504
|
attribute_will_change!(#{name.inspect})
|
|
379
505
|
attributes[#{name.inspect}] = value
|
|
@@ -387,11 +513,13 @@ module Mongoid #:nodoc
|
|
|
387
513
|
#
|
|
388
514
|
# @example Include the fields.
|
|
389
515
|
# Person.generated_methods
|
|
516
|
+
#
|
|
517
|
+
# @return [ Module ] The module of generated methods.
|
|
518
|
+
#
|
|
519
|
+
# @since 2.0.0
|
|
390
520
|
def generated_methods
|
|
391
521
|
@generated_methods ||= begin
|
|
392
|
-
Module.new.tap
|
|
393
|
-
include mod
|
|
394
|
-
end
|
|
522
|
+
Module.new.tap { |mod| include(mod) }
|
|
395
523
|
end
|
|
396
524
|
end
|
|
397
525
|
end
|
data/lib/mongoid/hierarchy.rb
CHANGED
|
@@ -69,7 +69,12 @@ module Mongoid #:nodoc
|
|
|
69
69
|
# @since 2.0.0.beta.1
|
|
70
70
|
def remove_child(child)
|
|
71
71
|
name = child.metadata.name
|
|
72
|
-
child.embedded_one?
|
|
72
|
+
if child.embedded_one?
|
|
73
|
+
remove_ivar(name)
|
|
74
|
+
else
|
|
75
|
+
relation = send(name)
|
|
76
|
+
relation.send(:delete_one, child)
|
|
77
|
+
end
|
|
73
78
|
end
|
|
74
79
|
|
|
75
80
|
# After children are persisted we can call this to move all their changes
|
data/lib/mongoid/identity_map.rb
CHANGED
|
@@ -4,6 +4,21 @@ module Mongoid #:nodoc:
|
|
|
4
4
|
# Defines behaviour for the identity map in Mongoid.
|
|
5
5
|
class IdentityMap < Hash
|
|
6
6
|
|
|
7
|
+
# Clear the many documents.
|
|
8
|
+
#
|
|
9
|
+
# @example Clear the docs.
|
|
10
|
+
# identity_map.clear_many(Post, selector)
|
|
11
|
+
#
|
|
12
|
+
# @param [ Class ] klass The klass to clear.
|
|
13
|
+
# @param [ Hash ] selector The selector to identify it.
|
|
14
|
+
#
|
|
15
|
+
# @return [ Array<Document> ] The documents.
|
|
16
|
+
#
|
|
17
|
+
# @since 2.4.10
|
|
18
|
+
def clear_many(klass, selector)
|
|
19
|
+
(documents_for(klass)[selector] ||= []).clear
|
|
20
|
+
end
|
|
21
|
+
|
|
7
22
|
# Get a document from the identity map by its id.
|
|
8
23
|
#
|
|
9
24
|
# @example Get the document from the map.
|
data/lib/mongoid/logger.rb
CHANGED
|
@@ -4,7 +4,13 @@ module Mongoid #:nodoc:
|
|
|
4
4
|
# The Mongoid logger which wraps some other ruby compliant logger class.
|
|
5
5
|
class Logger
|
|
6
6
|
|
|
7
|
-
delegate
|
|
7
|
+
delegate \
|
|
8
|
+
:info,
|
|
9
|
+
:debug,
|
|
10
|
+
:error,
|
|
11
|
+
:fatal,
|
|
12
|
+
:level,
|
|
13
|
+
:unknown, :to => :logger, :allow_nil => true
|
|
8
14
|
|
|
9
15
|
# Emit a warning log message.
|
|
10
16
|
#
|
data/lib/mongoid/matchers/all.rb
CHANGED
|
@@ -14,7 +14,14 @@ module Mongoid #:nodoc:
|
|
|
14
14
|
#
|
|
15
15
|
# @return [ true, false ] If the values match.
|
|
16
16
|
def matches?(value)
|
|
17
|
-
|
|
17
|
+
attribute_array = Array.wrap(@attribute)
|
|
18
|
+
value.values.first.all? do |e|
|
|
19
|
+
if e.is_a?(Regexp)
|
|
20
|
+
attribute_array.any? { |_attribute| _attribute =~ e }
|
|
21
|
+
else
|
|
22
|
+
attribute_array.include?(e)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
18
25
|
end
|
|
19
26
|
end
|
|
20
27
|
end
|
data/lib/mongoid/matchers/in.rb
CHANGED
|
@@ -14,7 +14,14 @@ module Mongoid #:nodoc:
|
|
|
14
14
|
#
|
|
15
15
|
# @return [ true, false ] If a value exists.
|
|
16
16
|
def matches?(value)
|
|
17
|
-
Array.wrap(@attribute)
|
|
17
|
+
attribute_array = Array.wrap(@attribute)
|
|
18
|
+
value.values.first.any? do |e|
|
|
19
|
+
if e.is_a?(Regexp)
|
|
20
|
+
attribute_array.any? { |_attribute| _attribute =~ e }
|
|
21
|
+
else
|
|
22
|
+
attribute_array.include?(e)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
18
25
|
end
|
|
19
26
|
end
|
|
20
27
|
end
|
|
@@ -81,8 +81,12 @@ module Mongoid #:nodoc:
|
|
|
81
81
|
# @since 2.2.1
|
|
82
82
|
def extract_attribute(document, key)
|
|
83
83
|
if (key_string = key.to_s) =~ /.+\..+/
|
|
84
|
-
key_string.split('.').inject(document.attributes) do |
|
|
85
|
-
|
|
84
|
+
key_string.split('.').inject(document.attributes) do |_attribs, _key|
|
|
85
|
+
if _attribs.is_a?(::Array)
|
|
86
|
+
_attribs.map { |doc| doc.try(:[], _key) }
|
|
87
|
+
else
|
|
88
|
+
_attribs.try(:[], _key)
|
|
89
|
+
end
|
|
86
90
|
end
|
|
87
91
|
else
|
|
88
92
|
document.attributes[key_string]
|