forked from mongodb/mongoid
/
foreign_key.rb
140 lines (131 loc) · 3.89 KB
/
foreign_key.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# encoding: utf-8
module Mongoid
module Fields
class ForeignKey < Standard
# Adds the atomic changes for this type of resizable field.
#
# @example Add the atomic changes.
# field.add_atomic_changes(doc, "key", {}, [], [])
#
# @todo: Durran: Refactor, big time.
#
# @param [ Document ] document The document to add to.
# @param [ String ] name The name of the field.
# @param [ String ] key The atomic location of the field.
# @param [ Hash ] mods The current modifications.
# @param [ Array ] new The new elements to add.
# @param [ Array ] old The old elements getting removed.
#
# @since 2.4.0
def add_atomic_changes(document, name, key, mods, new_elements, old_elements)
old = (old_elements || [])
new = (new_elements || [])
if new.length > old.length
if new.first(old.length) == old
document.atomic_array_add_to_sets[key] = new.drop(old.length)
else
mods[key] = document.attributes[name]
end
elsif new.length < old.length
pulls = old - new
if new == old - pulls
document.atomic_array_pulls[key] = pulls
else
mods[key] = document.attributes[name]
end
elsif new != old
mods[key] = document.attributes[name]
end
end
# Is this field a foreign key?
#
# @example Is the field a foreign key?
# field.foreign_key?
#
# @return [ true, false ] If the field is a foreign key.
#
# @since 2.4.0
def foreign_key?
true
end
# Evolve the object into an id compatible object.
#
# @example Evolve the object.
# field.evolve(object)
#
# @param [ Object ] object The object to evolve.
#
# @return [ Object ] The evolved object.
#
# @since 3.0.0
def evolve(object)
if object_id_field?
object.__evolve_object_id__
else
related_id_field.evolve(object)
end
end
# Mongoize the object into the Mongo friendly value.
#
# @example Mongoize the object.
# field.mongoize(object)
#
# @param [ Object ] object The object to Mongoize.
#
# @return [ Object ] The mongoized object.
#
# @since 3.0.0
def mongoize(object)
if type.resizable? || object_id_field?
type.__mongoize_fk__(constraint, object)
else
related_id_field.mongoize(object)
end
end
# Is the field a Moped::BSON::ObjectId?
#
# @example Is the field a Moped::BSON::ObjectId?
# field.object_id_field?
#
# @return [ true, false ] If the field is a Moped::BSON::ObjectId.
#
# @since 2.2.0
def object_id_field?
@object_id_field ||=
metadata.polymorphic? ? true : metadata.klass.using_object_ids?
end
private
# Evaluate the default proc. In some cases we need to instance exec,
# in others we don't.
#
# @example Eval the default proc.
# field.evaluate_default_proc(band)
#
# @param [ Document ] doc The document.
#
# @return [ Object ] The called proc.
#
# @since 3.0.0
def evaluate_default_proc(doc)
serialize_default(default_val[])
end
def related_id_field
@related_id_field ||= metadata.klass.fields["_id"]
end
# This is used when default values need to be serialized. Most of the
# time just return the object.
#
# @api private
#
# @example Serialize the default value.
# field.serialize_default(obj)
#
# @param [ Object ] object The default.
#
# @return [ Object ] The serialized default.
#
# @since 3.0.0
def serialize_default(object); object; end
end
end
end