mongoid 2.0.0.rc.6 → 2.0.0.rc.7
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/Rakefile +2 -2
- data/lib/config/locales/bg.yml +3 -6
- data/lib/config/locales/de.yml +2 -5
- data/lib/config/locales/en.yml +2 -5
- data/lib/config/locales/es.yml +2 -5
- data/lib/config/locales/fr.yml +2 -5
- data/lib/config/locales/hu.yml +2 -5
- data/lib/config/locales/it.yml +2 -5
- data/lib/config/locales/kr.yml +2 -5
- data/lib/config/locales/nl.yml +2 -5
- data/lib/config/locales/pl.yml +2 -5
- data/lib/config/locales/pt-br.yml +2 -5
- data/lib/config/locales/pt.yml +2 -5
- data/lib/config/locales/ro.yml +2 -5
- data/lib/config/locales/ru.yml +41 -0
- data/lib/config/locales/sv.yml +2 -5
- data/lib/config/locales/zh-CN.yml +3 -6
- data/lib/mongoid/atomicity.rb +2 -2
- data/lib/mongoid/attributes.rb +40 -69
- data/lib/mongoid/attributes/processing.rb +142 -0
- data/lib/mongoid/collections.rb +1 -0
- data/lib/mongoid/components.rb +1 -1
- data/lib/mongoid/config.rb +0 -1
- data/lib/mongoid/contexts/mongo.rb +13 -9
- data/lib/mongoid/criteria.rb +15 -1
- data/lib/mongoid/criterion/inclusion.rb +36 -11
- data/lib/mongoid/criterion/inspection.rb +3 -1
- data/lib/mongoid/criterion/optional.rb +2 -2
- data/lib/mongoid/dirty.rb +1 -0
- data/lib/mongoid/document.rb +11 -5
- data/lib/mongoid/extensions/integer/conversions.rb +2 -2
- data/lib/mongoid/extensions/object_id/conversions.rb +62 -32
- data/lib/mongoid/field.rb +5 -2
- data/lib/mongoid/identity.rb +2 -1
- data/lib/mongoid/matchers.rb +5 -32
- data/lib/mongoid/matchers/default.rb +53 -10
- data/lib/mongoid/matchers/or.rb +30 -0
- data/lib/mongoid/matchers/strategies.rb +63 -0
- data/lib/mongoid/multi_parameter_attributes.rb +4 -2
- data/lib/mongoid/nested_attributes.rb +8 -0
- data/lib/mongoid/persistence.rb +2 -1
- data/lib/mongoid/persistence/insert.rb +3 -3
- data/lib/mongoid/persistence/insert_embedded.rb +2 -1
- data/lib/mongoid/relations.rb +2 -1
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +4 -2
- data/lib/mongoid/relations/builders/nested_attributes/many.rb +2 -0
- data/lib/mongoid/relations/cascading.rb +1 -1
- data/lib/mongoid/relations/cascading/nullify.rb +1 -1
- data/lib/mongoid/relations/constraint.rb +42 -0
- data/lib/mongoid/relations/cyclic.rb +6 -0
- data/lib/mongoid/relations/embedded/many.rb +4 -4
- data/lib/mongoid/relations/macros.rb +1 -1
- data/lib/mongoid/relations/many.rb +1 -0
- data/lib/mongoid/relations/metadata.rb +12 -4
- data/lib/mongoid/relations/nested_builder.rb +1 -3
- data/lib/mongoid/relations/referenced/many.rb +11 -18
- data/lib/mongoid/relations/referenced/many_to_many.rb +19 -32
- data/lib/mongoid/relations/referenced/one.rb +3 -1
- data/lib/mongoid/timestamps.rb +1 -1
- data/lib/mongoid/validations/associated.rb +11 -9
- data/lib/mongoid/validations/uniqueness.rb +1 -1
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid/versioning.rb +2 -2
- metadata +9 -4
data/lib/mongoid/field.rb
CHANGED
@@ -51,8 +51,11 @@ module Mongoid #:nodoc:
|
|
51
51
|
unless options[:identity]
|
52
52
|
type.set(object)
|
53
53
|
else
|
54
|
-
|
55
|
-
|
54
|
+
if object.blank?
|
55
|
+
type.set(object)
|
56
|
+
else
|
57
|
+
options[:metadata].constraint.convert(object)
|
58
|
+
end
|
56
59
|
end
|
57
60
|
end
|
58
61
|
|
data/lib/mongoid/identity.rb
CHANGED
data/lib/mongoid/matchers.rb
CHANGED
@@ -1,15 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require "mongoid/matchers/
|
3
|
-
require "mongoid/matchers/all"
|
4
|
-
require "mongoid/matchers/exists"
|
5
|
-
require "mongoid/matchers/gt"
|
6
|
-
require "mongoid/matchers/gte"
|
7
|
-
require "mongoid/matchers/in"
|
8
|
-
require "mongoid/matchers/lt"
|
9
|
-
require "mongoid/matchers/lte"
|
10
|
-
require "mongoid/matchers/ne"
|
11
|
-
require "mongoid/matchers/nin"
|
12
|
-
require "mongoid/matchers/size"
|
2
|
+
require "mongoid/matchers/strategies"
|
13
3
|
|
14
4
|
module Mongoid #:nodoc:
|
15
5
|
|
@@ -28,28 +18,11 @@ module Mongoid #:nodoc:
|
|
28
18
|
# @return [ true, false ] True if matches, false if not.
|
29
19
|
def matches?(selector)
|
30
20
|
selector.each_pair do |key, value|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
protected
|
36
|
-
|
37
|
-
# Get the matcher for the supplied key and value. Will determine the class
|
38
|
-
# name from the key.
|
39
|
-
#
|
40
|
-
# @example Get the matcher.
|
41
|
-
# document.matcher(:title, { "$in" => [ "test" ] })
|
42
|
-
#
|
43
|
-
# @param [ Symbol, String ] key The field name.
|
44
|
-
# @param [ Object, Hash ] The value or selector.
|
45
|
-
#
|
46
|
-
# @return [ Matcher ] The matcher.
|
47
|
-
def matcher(key, value)
|
48
|
-
if value.is_a?(Hash)
|
49
|
-
name = "Mongoid::Matchers::#{value.keys.first.gsub("$", "").camelize}"
|
50
|
-
return name.constantize.new(attributes[key])
|
21
|
+
unless Strategies.matcher(self, key, value).matches?(value)
|
22
|
+
return false
|
23
|
+
end
|
51
24
|
end
|
52
|
-
|
25
|
+
return true
|
53
26
|
end
|
54
27
|
end
|
55
28
|
end
|
@@ -1,26 +1,69 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Mongoid #:nodoc:
|
3
3
|
module Matchers #:nodoc:
|
4
|
+
|
5
|
+
# Contains all the default behavior for checking for matching documents
|
6
|
+
# given MongoDB expressions.
|
4
7
|
class Default
|
8
|
+
|
9
|
+
attr_accessor :attribute, :document
|
10
|
+
|
5
11
|
# Creating a new matcher only requires the value.
|
6
|
-
|
7
|
-
|
12
|
+
#
|
13
|
+
# @example Create a new matcher.
|
14
|
+
# Default.new("attribute")
|
15
|
+
#
|
16
|
+
# @param [ Object ] attribute The current attribute to check against.
|
17
|
+
#
|
18
|
+
# @since 1.0.0
|
19
|
+
def initialize(attribute, document = nil)
|
20
|
+
@attribute, @document = attribute, document
|
8
21
|
end
|
9
|
-
|
22
|
+
|
23
|
+
# Return true if the attribute and value are equal, or if it is an array
|
24
|
+
# if the value is included.
|
25
|
+
#
|
26
|
+
# @example Does this value match?
|
27
|
+
# default.matches?("value")
|
28
|
+
#
|
29
|
+
# @param [ Object ] value The value to check if it matches.
|
30
|
+
#
|
31
|
+
# @return [ true, false ] True if matches, false if not.
|
32
|
+
#
|
33
|
+
# @since 1.0.0
|
10
34
|
def matches?(value)
|
11
|
-
|
12
|
-
@attribute.include?(value) : value === @attribute
|
35
|
+
attribute.is_a?(Array) ? attribute.include?(value) : value === attribute
|
13
36
|
end
|
14
37
|
|
15
38
|
protected
|
16
|
-
|
17
|
-
|
18
|
-
|
39
|
+
|
40
|
+
# Convenience method for getting the first value in a hash.
|
41
|
+
#
|
42
|
+
# @example Get the first value.
|
43
|
+
# matcher.first(:test => "value")
|
44
|
+
#
|
45
|
+
# @param [ Hash ] hash The has to pull from.
|
46
|
+
#
|
47
|
+
# @return [ Object ] The first value.
|
48
|
+
#
|
49
|
+
# @since 1.0.0
|
50
|
+
def first(hash)
|
51
|
+
hash.values.first
|
19
52
|
end
|
20
53
|
|
21
|
-
# If object exists then compare,
|
54
|
+
# If object exists then compare the two, otherwise return false
|
55
|
+
#
|
56
|
+
# @example Determine if we can compare.
|
57
|
+
# matcher.determine("test", "$in")
|
58
|
+
#
|
59
|
+
# @param [ Object ] value The value to compare with.
|
60
|
+
# @param [ Symbol, String ] operator The comparison operation.
|
61
|
+
#
|
62
|
+
# @return [ true, false ] The comparison or false.
|
63
|
+
#
|
64
|
+
# @since 1.0.0
|
22
65
|
def determine(value, operator)
|
23
|
-
|
66
|
+
attribute ? attribute.send(operator, first(value)) : false
|
24
67
|
end
|
25
68
|
end
|
26
69
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid #:nodoc:
|
3
|
+
module Matchers #:nodoc:
|
4
|
+
|
5
|
+
# Defines behavior for handling $or expressions in embedded documents.
|
6
|
+
class Or < Default
|
7
|
+
|
8
|
+
# Does the supplied query match the attribute?
|
9
|
+
#
|
10
|
+
# @example Does this match?
|
11
|
+
# matcher.matches?("$or" => [ { field => value } ])
|
12
|
+
#
|
13
|
+
# @param [ Array ] conditions The or expression.
|
14
|
+
#
|
15
|
+
# @return [ true, false ] True if matches, false if not.
|
16
|
+
#
|
17
|
+
# @since 2.0.0.rc.7
|
18
|
+
def matches?(conditions)
|
19
|
+
conditions.each do |condition|
|
20
|
+
key = condition.keys.first
|
21
|
+
value = condition.values.first
|
22
|
+
if Strategies.matcher(document, key, value).matches?(value)
|
23
|
+
return true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
return false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "mongoid/matchers/default"
|
3
|
+
require "mongoid/matchers/all"
|
4
|
+
require "mongoid/matchers/exists"
|
5
|
+
require "mongoid/matchers/gt"
|
6
|
+
require "mongoid/matchers/gte"
|
7
|
+
require "mongoid/matchers/in"
|
8
|
+
require "mongoid/matchers/lt"
|
9
|
+
require "mongoid/matchers/lte"
|
10
|
+
require "mongoid/matchers/ne"
|
11
|
+
require "mongoid/matchers/nin"
|
12
|
+
require "mongoid/matchers/or"
|
13
|
+
require "mongoid/matchers/size"
|
14
|
+
|
15
|
+
module Mongoid #:nodoc:
|
16
|
+
module Matchers #:nodoc:
|
17
|
+
|
18
|
+
# This module is responsible for returning the correct matcher given a
|
19
|
+
# MongoDB query expression.
|
20
|
+
module Strategies
|
21
|
+
extend self
|
22
|
+
|
23
|
+
MATCHERS = {
|
24
|
+
"$all" => Matchers::All,
|
25
|
+
"$exists" => Matchers::Exists,
|
26
|
+
"$gt" => Matchers::Gt,
|
27
|
+
"$gte" => Matchers::Gte,
|
28
|
+
"$in" => Matchers::In,
|
29
|
+
"$lt" => Matchers::Lt,
|
30
|
+
"$lte" => Matchers::Lte,
|
31
|
+
"$ne" => Matchers::Ne,
|
32
|
+
"$nin" => Matchers::Nin,
|
33
|
+
"$or" => Matchers::Or,
|
34
|
+
"$size" => Matchers::Size
|
35
|
+
}
|
36
|
+
|
37
|
+
# Get the matcher for the supplied key and value. Will determine the class
|
38
|
+
# name from the key.
|
39
|
+
#
|
40
|
+
# @example Get the matcher.
|
41
|
+
# document.matcher(:title, { "$in" => [ "test" ] })
|
42
|
+
#
|
43
|
+
# @param [ Document ] document The document to check.
|
44
|
+
# @param [ Symbol, String ] key The field name.
|
45
|
+
# @param [ Object, Hash ] The value or selector.
|
46
|
+
#
|
47
|
+
# @return [ Matcher ] The matcher.
|
48
|
+
#
|
49
|
+
# @since 2.0.0.rc.7
|
50
|
+
def matcher(document, key, value)
|
51
|
+
if value.is_a?(Hash)
|
52
|
+
MATCHERS[value.keys.first].new(document.attributes[key])
|
53
|
+
else
|
54
|
+
if key == "$or"
|
55
|
+
Matchers::Or.new(value, document)
|
56
|
+
else
|
57
|
+
Default.new(document.attributes[key])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Mongoid #:nodoc:
|
3
|
+
|
4
|
+
# @todo: Durran: This module needs an overhaul.
|
3
5
|
module MultiParameterAttributes
|
4
6
|
module Errors
|
5
7
|
# Raised when an error occurred while doing a mass assignment to an attribute through the
|
@@ -64,9 +66,9 @@ module Mongoid #:nodoc:
|
|
64
66
|
|
65
67
|
def instantiate_object(klass, values_with_empty_parameters)
|
66
68
|
return nil if values_with_empty_parameters.all? { |v| v.nil? }
|
67
|
-
|
69
|
+
|
68
70
|
values = values_with_empty_parameters.collect { |v| v.nil? ? 1 : v }
|
69
|
-
|
71
|
+
|
70
72
|
if klass == DateTime || klass == Date || klass == Time
|
71
73
|
klass.send(:convert_to_time, values)
|
72
74
|
elsif klass
|
@@ -3,6 +3,13 @@ module Mongoid #:nodoc:
|
|
3
3
|
module NestedAttributes
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
+
included do
|
7
|
+
class_attribute :nested_attributes
|
8
|
+
self.nested_attributes = []
|
9
|
+
|
10
|
+
delegate :nested_attributes, :to => "self.class"
|
11
|
+
end
|
12
|
+
|
6
13
|
module ClassMethods
|
7
14
|
REJECT_ALL_BLANK_PROC = proc { |attributes| attributes.all? { |_, value| value.blank? } }
|
8
15
|
|
@@ -32,6 +39,7 @@ module Mongoid #:nodoc:
|
|
32
39
|
options = args.extract_options!
|
33
40
|
options[:reject_if] = REJECT_ALL_BLANK_PROC if options[:reject_if] == :all_blank
|
34
41
|
args.each do |name|
|
42
|
+
self.nested_attributes += [ "#{name}_attributes=" ]
|
35
43
|
define_method("#{name}_attributes=") do |attrs|
|
36
44
|
relation = relations[name.to_s]
|
37
45
|
relation.nested_builder(attrs, options).build(self)
|
data/lib/mongoid/persistence.rb
CHANGED
@@ -55,6 +55,7 @@ module Mongoid #:nodoc:
|
|
55
55
|
# @return [ TrueClass ] True.
|
56
56
|
def remove(options = {})
|
57
57
|
if Remove.new(self, options).persist
|
58
|
+
raw_attributes.freeze
|
58
59
|
self.destroyed = true
|
59
60
|
cascade!
|
60
61
|
end; true
|
@@ -71,7 +72,7 @@ module Mongoid #:nodoc:
|
|
71
72
|
#
|
72
73
|
# @return [ true, false ] True if validation passed.
|
73
74
|
def save!(options = {})
|
74
|
-
self.class.fail_validate!(self) unless upsert; true
|
75
|
+
self.class.fail_validate!(self) unless upsert(options); true
|
75
76
|
end
|
76
77
|
|
77
78
|
# Update the document in the datbase.
|
@@ -25,8 +25,8 @@ module Mongoid #:nodoc:
|
|
25
25
|
# The +Document+, whether the insert succeeded or not.
|
26
26
|
def persist
|
27
27
|
return document if validate && document.invalid?(:create)
|
28
|
-
document.run_callbacks(:
|
29
|
-
document.run_callbacks(:
|
28
|
+
document.run_callbacks(:save) do
|
29
|
+
document.run_callbacks(:create) do
|
30
30
|
if insert
|
31
31
|
document.new_record = false
|
32
32
|
document._children.each { |child| child.new_record = false }
|
@@ -45,7 +45,7 @@ module Mongoid #:nodoc:
|
|
45
45
|
options.merge(:validate => validate)
|
46
46
|
).persist
|
47
47
|
else
|
48
|
-
collection.insert(document.
|
48
|
+
collection.insert(document.as_document, options)
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
@@ -31,9 +31,10 @@ module Mongoid #:nodoc:
|
|
31
31
|
if parent.new_record?
|
32
32
|
parent.insert
|
33
33
|
else
|
34
|
-
update = { document._inserter => { document._position => document.
|
34
|
+
update = { document._inserter => { document._position => document.as_document } }
|
35
35
|
collection.update(parent._selector, update, options.merge(:multi => false))
|
36
36
|
document.new_record = false
|
37
|
+
document.move_changes
|
37
38
|
end
|
38
39
|
document
|
39
40
|
end
|
data/lib/mongoid/relations.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
require "mongoid/relations/accessors"
|
3
3
|
require "mongoid/relations/auto_save"
|
4
4
|
require "mongoid/relations/cascading"
|
5
|
+
require "mongoid/relations/constraint"
|
5
6
|
require "mongoid/relations/cyclic"
|
6
7
|
require "mongoid/relations/proxy"
|
7
8
|
require "mongoid/relations/bindings"
|
@@ -50,7 +51,7 @@ module Mongoid # :nodoc:
|
|
50
51
|
#
|
51
52
|
# @since 2.0.0.rc.1
|
52
53
|
def embedded?
|
53
|
-
_parent.present?
|
54
|
+
cyclic ? _parent.present? : self.class.embedded?
|
54
55
|
end
|
55
56
|
|
56
57
|
# Determine if the document is part of an embeds_many relation.
|
@@ -50,7 +50,7 @@ module Mongoid # :nodoc:
|
|
50
50
|
inverse,
|
51
51
|
false,
|
52
52
|
OPTIONS
|
53
|
-
).push(base, :continue => false)
|
53
|
+
).push(base, :binding => true, :continue => false)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
@@ -88,7 +88,9 @@ module Mongoid # :nodoc:
|
|
88
88
|
if options[:continue]
|
89
89
|
inverse = metadata.inverse(target)
|
90
90
|
if inverse
|
91
|
-
doc.do_or_do_not(
|
91
|
+
doc.do_or_do_not(
|
92
|
+
inverse, false, OPTIONS
|
93
|
+
).delete(base, :binding => true, :continue => false)
|
92
94
|
end
|
93
95
|
end
|
94
96
|
end
|
@@ -106,6 +106,8 @@ module Mongoid # :nodoc:
|
|
106
106
|
document = existing.find(convert_id(attrs[:id]))
|
107
107
|
destroyable?(attrs) ? document.destroy : document.update_attributes(attrs)
|
108
108
|
else
|
109
|
+
# @todo: Durran: Tell the push not to save the base and call it
|
110
|
+
# after all processing is done. This is related to #581.
|
109
111
|
existing.push(metadata.klass.new(attrs)) unless destroyable?(attrs)
|
110
112
|
end
|
111
113
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid # :nodoc:
|
3
|
+
module Relations #:nodoc:
|
4
|
+
|
5
|
+
# Used for converting foreign key values to the correct type based on the
|
6
|
+
# types of ids that the document stores.
|
7
|
+
#
|
8
|
+
# @note Durran: The name of this class is this way to match the metadata
|
9
|
+
# getter, and foreign_key was already taken there.
|
10
|
+
class Constraint
|
11
|
+
attr_reader :metadata
|
12
|
+
|
13
|
+
# Create the new constraint with the metadata.
|
14
|
+
#
|
15
|
+
# @example Instantiate the constraint.
|
16
|
+
# Constraint.new(metdata)
|
17
|
+
#
|
18
|
+
# @param [ Metadata ] metadata The metadata of the relation.
|
19
|
+
#
|
20
|
+
# @since 2.0.0.rc.7
|
21
|
+
def initialize(metadata)
|
22
|
+
@metadata = metadata
|
23
|
+
end
|
24
|
+
|
25
|
+
# Convert the supplied object to the appropriate type to set as the
|
26
|
+
# foreign key for a relation.
|
27
|
+
#
|
28
|
+
# @example Convert the object.
|
29
|
+
# constraint.convert("12345")
|
30
|
+
#
|
31
|
+
# @param [ Object ] object The object to convert.
|
32
|
+
#
|
33
|
+
# @return [ Object ] The object cast to the correct type.
|
34
|
+
#
|
35
|
+
# @since 2.0.0.rc.7
|
36
|
+
def convert(object)
|
37
|
+
return object if metadata.polymorphic?
|
38
|
+
BSON::ObjectId.convert(metadata.klass, object)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|