forked from mongodb/mongoid
/
identity_map.rb
135 lines (124 loc) · 3.89 KB
/
identity_map.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
# encoding: utf-8
module Mongoid #:nodoc:
# Defines behaviour for the identity map in Mongoid.
class IdentityMap < Hash
# Clear the many documents.
#
# @example Clear the docs.
# identity_map.clear_many(Post, selector)
#
# @param [ Class ] klass The klass to clear.
# @param [ Hash ] selector The selector to identify it.
#
# @return [ Array<Document> ] The documents.
#
# @since 2.4.10
def clear_many(klass, selector)
(documents_for(klass)[selector] ||= []).clear
end
# Get a document from the identity map by its id.
#
# @example Get the document from the map.
# map.get(Person, id)
#
# @param [ Class ] klass The class of the document.
# @param [ Object, Hash ] idenfier The document id or selector.
#
# @return [ Document ] The matching document.
#
# @since 2.1.0
def get(klass, identifier)
return nil unless Mongoid.identity_map_enabled? && klass
documents_for(klass)[identifier]
end
# Remove the document from the identity map.
#
# @example Remove the document.
# map.removed(person)
#
# @param [ Document ] document The document to remove.
#
# @return [ Document, nil ] The removed document.
#
# @since 2.1.0
def remove(document)
return nil unless Mongoid.identity_map_enabled? && document && document.id
documents_for(document.class).delete(document.id)
end
# Puts a document in the identity map, accessed by it's id.
#
# @example Put the document in the map.
# identity_map.set(document)
#
# @param [ Document ] document The document to place in the map.
#
# @return [ Document ] The provided document.
#
# @since 2.1.0
def set(document)
return nil unless Mongoid.identity_map_enabled? && document && document.id
documents_for(document.class)[document.id] = document
end
# Set a document in the identity map for the provided selector.
#
# @example Set the document in the map.
# identity_map.set_selector(document, { :person_id => person.id })
#
# @param [ Document ] document The document to set.
# @param [ Hash ] selector The selector to identify it.
#
# @return [ Array<Document> ] The documents.
#
# @since 2.2.0
def set_many(document, selector)
(documents_for(document.class)[selector] ||= []).push(document)
end
# Set a document in the identity map for the provided selector.
#
# @example Set the document in the map.
# identity_map.set_selector(document, { :person_id => person.id })
#
# @param [ Document ] document The document to set.
# @param [ Hash ] selector The selector to identify it.
#
# @return [ Document ] The matching document.
#
# @since 2.2.0
def set_one(document, selector)
documents_for(document.class)[selector] = document
end
private
# Get the documents in the identity map for a specific class.
#
# @example Get the documents for the class.
# map.documents_for(Person)
#
# @param [ Class ] klass The class to retrieve.
#
# @return [ Hash ] The documents.
#
# @since 2.1.0
def documents_for(klass)
return nil unless klass
self[klass.collection_name] ||= {}
end
class << self
# For ease of access we provide the same API to the identity map on the
# class level, which in turn just gets the identity map that is on the
# current thread.
#
# @example Get a document from the current identity map by id.
# IdentityMap.get(id)
#
# @example Set a document in the current identity map.
# IdentityMap.set(document)
#
# @since 2.1.0
delegate *(
Hash.public_instance_methods(false) +
IdentityMap.public_instance_methods(false) <<
{ :to => :"Mongoid::Threaded.identity_map" }
)
end
end
end