Module: Mongoid::Ancestry
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/mongoid-ancestry.rb,
lib/mongoid-ancestry/version.rb,
lib/mongoid-ancestry/exceptions.rb,
lib/mongoid-ancestry/class_methods.rb,
lib/mongoid-ancestry/instance_methods.rb
Defined Under Namespace
Modules: ClassMethods
Classes: Error, IntegrityError
Constant Summary
collapse
- VERSION =
'0.2.3'
Instance Method Summary
collapse
Instance Method Details
#ancestor_conditions ⇒ Object
82
83
84
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 82
def ancestor_conditions
{ :_id.in => ancestor_ids }
end
|
#ancestor_ids ⇒ Object
78
79
80
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 78
def ancestor_ids
read_attribute(self.base_class.ancestry_field).to_s.split('/').map { |id| cast_primary_key(id) }
end
|
#ancestors(depth_options = {}) ⇒ Object
86
87
88
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 86
def ancestors depth_options = {}
self.base_class.scope_depth(depth_options, depth).where(ancestor_conditions)
end
|
#ancestry_callbacks_disabled? ⇒ Boolean
222
223
224
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 222
def ancestry_callbacks_disabled?
!!@disable_ancestry_callbacks
end
|
#ancestry_exclude_self ⇒ Object
Validate that the ancestors don’t include itself
5
6
7
8
9
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 5
def ancestry_exclude_self
if ancestor_ids.include? id
errors.add(:base, "#{self.class.name.humanize} cannot be a descendant of itself.")
end
end
|
#apply_orphan_strategy ⇒ Object
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
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 36
def apply_orphan_strategy
unless ancestry_callbacks_disabled?
unless new_record?
if self.base_class.orphan_strategy == :rootify
descendants.each do |descendant|
descendant.without_ancestry_callbacks do
val = \
unless descendant.ancestry == child_ancestry
descendant.read_attribute(descendant.class.ancestry_field).gsub(/^#{child_ancestry}\//, '')
end
descendant.update_attribute descendant.class.ancestry_field, val
end
end
elsif self.base_class.orphan_strategy == :destroy
descendants.all.each do |descendant|
descendant.without_ancestry_callbacks { descendant.destroy }
end
elsif self.base_class.orphan_strategy == :restrict
raise Error.new('Cannot delete record because it has descendants.') unless is_childless?
end
end
end
end
|
#cache_depth ⇒ Object
106
107
108
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 106
def cache_depth
write_attribute self.base_class.depth_cache_field, depth
end
|
#child_ancestry ⇒ Object
The ancestry value for this record’s children
66
67
68
69
70
71
72
73
74
75
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 66
def child_ancestry
raise Error.new('No child ancestry for new record. Save record before performing tree operations.') if new_record?
if self.send("#{self.base_class.ancestry_field}_was").blank?
id.to_s
else
"#{self.send "#{self.base_class.ancestry_field}_was"}/#{id}"
end
end
|
#child_conditions ⇒ Object
141
142
143
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 141
def child_conditions
{self.base_class.ancestry_field => child_ancestry}
end
|
#child_ids ⇒ Object
149
150
151
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 149
def child_ids
children.only(:_id).map(&:id)
end
|
#children ⇒ Object
145
146
147
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 145
def children
self.base_class.where(child_conditions)
end
|
#depth ⇒ Object
102
103
104
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 102
def depth
ancestor_ids.size
end
|
#descendant_conditions ⇒ Object
183
184
185
186
187
188
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 183
def descendant_conditions
[
{ self.base_class.ancestry_field => /^#{child_ancestry}\// },
{ self.base_class.ancestry_field => child_ancestry }
]
end
|
#descendant_ids(depth_options = {}) ⇒ Object
194
195
196
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 194
def descendant_ids depth_options = {}
descendants(depth_options).only(:_id).map(&:id)
end
|
#descendants(depth_options = {}) ⇒ Object
190
191
192
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 190
def descendants depth_options = {}
self.base_class.scope_depth(depth_options, depth).any_of(descendant_conditions)
end
|
#has_children? ⇒ Boolean
153
154
155
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 153
def has_children?
self.children.present?
end
|
#has_siblings? ⇒ Boolean
174
175
176
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 174
def has_siblings?
self.siblings.count > 1
end
|
#is_childless? ⇒ Boolean
157
158
159
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 157
def is_childless?
!has_children?
end
|
#is_only_child? ⇒ Boolean
178
179
180
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 178
def is_only_child?
!has_siblings?
end
|
#is_root? ⇒ Boolean
136
137
138
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 136
def is_root?
read_attribute(self.base_class.ancestry_field).blank?
end
|
#parent ⇒ Object
123
124
125
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 123
def parent
parent_id.blank? ? nil : self.base_class.find(parent_id)
end
|
#parent=(parent) ⇒ Object
111
112
113
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 111
def parent= parent
write_attribute(self.base_class.ancestry_field, parent.blank? ? nil : parent.child_ancestry)
end
|
#parent_id ⇒ Object
119
120
121
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 119
def parent_id
ancestor_ids.empty? ? nil : ancestor_ids.last
end
|
#parent_id=(parent_id) ⇒ Object
115
116
117
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 115
def parent_id= parent_id
self.parent = parent_id.blank? ? nil : self.base_class.find(parent_id)
end
|
#path(depth_options = {}) ⇒ Object
98
99
100
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 98
def path depth_options = {}
self.base_class.scope_depth(depth_options, depth).where(path_conditions)
end
|
#path_conditions ⇒ Object
94
95
96
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 94
def path_conditions
{ :_id.in => path_ids }
end
|
#path_ids ⇒ Object
90
91
92
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 90
def path_ids
ancestor_ids + [id]
end
|
#root ⇒ Object
132
133
134
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 132
def root
(root_id == id) ? self : self.base_class.find(root_id)
end
|
#root_id ⇒ Object
128
129
130
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 128
def root_id
ancestor_ids.empty? ? id : ancestor_ids.first
end
|
#sibling_conditions ⇒ Object
162
163
164
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 162
def sibling_conditions
{self.base_class.ancestry_field => read_attribute(self.base_class.ancestry_field)}
end
|
#sibling_ids ⇒ Object
170
171
172
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 170
def sibling_ids
siblings.only(:_id).map(&:id)
end
|
#siblings ⇒ Object
166
167
168
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 166
def siblings
self.base_class.where sibling_conditions
end
|
#subtree(depth_options = {}) ⇒ Object
207
208
209
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 207
def subtree depth_options = {}
self.base_class.scope_depth(depth_options, depth).any_of(subtree_conditions)
end
|
#subtree_conditions ⇒ Object
199
200
201
202
203
204
205
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 199
def subtree_conditions
[
{ :_id => id },
{ self.base_class.ancestry_field => /^#{child_ancestry}\// },
{ self.base_class.ancestry_field => child_ancestry }
]
end
|
#subtree_ids(depth_options = {}) ⇒ Object
211
212
213
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 211
def subtree_ids depth_options = {}
subtree(depth_options).only(:_id).map(&:id)
end
|
#update_descendants_with_new_ancestry ⇒ Object
Update descendants with new ancestry
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 12
def update_descendants_with_new_ancestry
unless ancestry_callbacks_disabled?
if changed.include?(self.base_class.ancestry_field.to_s) && !new_record? && valid?
descendants.each do |descendant|
descendant.without_ancestry_callbacks do
for_replace = \
if read_attribute(self.class.ancestry_field).blank?
id.to_s
else
"#{read_attribute self.class.ancestry_field}/#{id}"
end
new_ancestry = descendant.read_attribute(descendant.class.ancestry_field).gsub(/^#{self.child_ancestry}/, for_replace)
descendant.update_attribute(self.base_class.ancestry_field, new_ancestry)
end
end
end
end
end
|
#without_ancestry_callbacks ⇒ Object
216
217
218
219
220
|
# File 'lib/mongoid-ancestry/instance_methods.rb', line 216
def without_ancestry_callbacks
@disable_ancestry_callbacks = true
yield
@disable_ancestry_callbacks = false
end
|