ancestry 2.2.2 → 3.0.0
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.
- checksums.yaml +4 -4
- data/README.md +430 -0
- data/ancestry.gemspec +5 -4
- data/lib/ancestry.rb +2 -1
- data/lib/ancestry/class_methods.rb +1 -7
- data/lib/ancestry/has_ancestry.rb +89 -88
- data/lib/ancestry/instance_methods.rb +76 -100
- data/lib/ancestry/materialized_path.rb +61 -0
- metadata +8 -6
- data/README.rdoc +0 -330
data/lib/ancestry.rb
CHANGED
@@ -2,7 +2,8 @@ require_relative 'ancestry/class_methods'
|
|
2
2
|
require_relative 'ancestry/instance_methods'
|
3
3
|
require_relative 'ancestry/exceptions'
|
4
4
|
require_relative 'ancestry/has_ancestry'
|
5
|
+
require_relative 'ancestry/materialized_path'
|
5
6
|
|
6
7
|
module Ancestry
|
7
8
|
ANCESTRY_PATTERN = /\A[0-9]+(\/[0-9]+)*\Z/
|
8
|
-
end
|
9
|
+
end
|
@@ -29,14 +29,8 @@ module Ancestry
|
|
29
29
|
|
30
30
|
# Arrangement
|
31
31
|
def arrange options = {}
|
32
|
-
scope =
|
33
|
-
if options[:order].nil?
|
34
|
-
self.ancestry_base_class.ordered_by_ancestry
|
35
|
-
else
|
36
|
-
self.ancestry_base_class.ordered_by_ancestry_and options.delete(:order)
|
37
|
-
end
|
38
32
|
# Get all nodes ordered by ancestry and start sorting them into an empty hash
|
39
|
-
arrange_nodes
|
33
|
+
arrange_nodes self.ancestry_base_class.reorder(options.delete(:order)).where(options)
|
40
34
|
end
|
41
35
|
|
42
36
|
# Arrange array of nodes into a nested hash of the form
|
@@ -1,104 +1,105 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
module Ancestry
|
2
|
+
module HasAncestry
|
3
|
+
def has_ancestry options = {}
|
4
|
+
# Check options
|
5
|
+
raise Ancestry::AncestryException.new("Options for has_ancestry must be in a hash.") unless options.is_a? Hash
|
6
|
+
options.each do |key, value|
|
7
|
+
unless [:ancestry_column, :orphan_strategy, :cache_depth, :depth_cache_column, :touch].include? key
|
8
|
+
raise Ancestry::AncestryException.new("Unknown option for has_ancestry: #{key.inspect} => #{value.inspect}.")
|
9
|
+
end
|
8
10
|
end
|
9
|
-
end
|
10
11
|
|
11
|
-
# Include instance methods
|
12
|
-
include Ancestry::InstanceMethods
|
13
|
-
|
14
|
-
# Include dynamic class methods
|
15
|
-
extend Ancestry::ClassMethods
|
16
|
-
|
17
|
-
# Create ancestry column accessor and set to option or default
|
18
|
-
cattr_accessor :ancestry_column
|
19
|
-
self.ancestry_column = options[:ancestry_column] || :ancestry
|
20
|
-
|
21
|
-
# Create orphan strategy accessor and set to option or default (writer comes from DynamicClassMethods)
|
22
|
-
cattr_reader :orphan_strategy
|
23
|
-
self.orphan_strategy = options[:orphan_strategy] || :destroy
|
24
|
-
|
25
|
-
# Save self as base class (for STI)
|
26
|
-
cattr_accessor :ancestry_base_class
|
27
|
-
self.ancestry_base_class = self
|
28
|
-
|
29
|
-
# Touch ancestors after updating
|
30
|
-
cattr_accessor :touch_ancestors
|
31
|
-
self.touch_ancestors = options[:touch] || false
|
32
|
-
|
33
|
-
# Validate format of ancestry column value
|
34
|
-
validates_format_of ancestry_column, :with => Ancestry::ANCESTRY_PATTERN, :allow_nil => true
|
35
|
-
|
36
|
-
# Validate that the ancestor ids don't include own id
|
37
|
-
validate :ancestry_exclude_self
|
38
|
-
|
39
|
-
# Named scopes
|
40
|
-
scope :roots, lambda { where(ancestry_column => nil) }
|
41
|
-
scope :ancestors_of, lambda { |object| where(to_node(object).ancestor_conditions) }
|
42
|
-
scope :children_of, lambda { |object| where(to_node(object).child_conditions) }
|
43
|
-
scope :descendants_of, lambda { |object| where(to_node(object).descendant_conditions) }
|
44
|
-
scope :subtree_of, lambda { |object| where(to_node(object).subtree_conditions) }
|
45
|
-
scope :siblings_of, lambda { |object| where(to_node(object).sibling_conditions) }
|
46
|
-
scope :ordered_by_ancestry, lambda {
|
47
|
-
if %w(mysql mysql2 sqlite postgresql).include?(connection.adapter_name.downcase) &&
|
48
|
-
defined?(ActiveRecord.version) && ActiveRecord.version.to_s >= "5"
|
49
|
-
reorder("coalesce(#{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)}, '')")
|
50
|
-
else
|
51
|
-
reorder("(CASE WHEN #{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)} IS NULL THEN 0 ELSE 1 END), #{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)}")
|
52
|
-
end
|
53
|
-
}
|
54
|
-
scope :ordered_by_ancestry_and, lambda { |order|
|
55
|
-
if %w(mysql mysql2 sqlite postgresql).include?(connection.adapter_name.downcase) &&
|
56
|
-
defined?(ActiveRecord.version) && ActiveRecord.version.to_s >= "5"
|
57
|
-
reorder("coalesce(#{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)}, ''), #{order}")
|
58
|
-
else
|
59
|
-
reorder("(CASE WHEN #{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)} IS NULL THEN 0 ELSE 1 END), #{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)}, #{order}")
|
60
|
-
end
|
61
|
-
}
|
62
|
-
scope :path_of, lambda { |object| to_node(object).path }
|
63
12
|
|
64
|
-
|
65
|
-
|
13
|
+
# Create ancestry column accessor and set to option or default
|
14
|
+
cattr_accessor :ancestry_column
|
15
|
+
self.ancestry_column = options[:ancestry_column] || :ancestry
|
66
16
|
|
67
|
-
|
68
|
-
|
17
|
+
# Save self as base class (for STI)
|
18
|
+
cattr_accessor :ancestry_base_class
|
19
|
+
self.ancestry_base_class = self
|
69
20
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
self.cattr_accessor :depth_cache_column
|
74
|
-
self.depth_cache_column = options[:depth_cache_column] || :ancestry_depth
|
21
|
+
# Touch ancestors after updating
|
22
|
+
cattr_accessor :touch_ancestors
|
23
|
+
self.touch_ancestors = options[:touch] || false
|
75
24
|
|
76
|
-
#
|
77
|
-
|
78
|
-
before_save :cache_depth
|
25
|
+
# Include instance methods
|
26
|
+
include Ancestry::InstanceMethods
|
79
27
|
|
80
|
-
#
|
81
|
-
|
82
|
-
end
|
28
|
+
# Include dynamic class methods
|
29
|
+
extend Ancestry::ClassMethods
|
83
30
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
31
|
+
extend Ancestry::MaterializedPath
|
32
|
+
|
33
|
+
# Create orphan strategy accessor and set to option or default (writer comes from DynamicClassMethods)
|
34
|
+
cattr_reader :orphan_strategy
|
35
|
+
self.orphan_strategy = options[:orphan_strategy] || :destroy
|
36
|
+
|
37
|
+
# Validate that the ancestor ids don't include own id
|
38
|
+
validate :ancestry_exclude_self
|
39
|
+
|
40
|
+
# Named scopes
|
41
|
+
scope :roots, lambda { where(root_conditions) }
|
42
|
+
scope :ancestors_of, lambda { |object| where(ancestor_conditions(object)) }
|
43
|
+
scope :path_of, lambda { |object| where(path_conditions(object)) }
|
44
|
+
scope :children_of, lambda { |object| where(child_conditions(object)) }
|
45
|
+
scope :descendants_of, lambda { |object| where(descendant_conditions(object)) }
|
46
|
+
scope :subtree_of, lambda { |object| where(subtree_conditions(object)) }
|
47
|
+
scope :siblings_of, lambda { |object| where(sibling_conditions(object)) }
|
48
|
+
scope :ordered_by_ancestry, Proc.new { |order|
|
49
|
+
if %w(mysql mysql2 sqlite sqlite3 postgresql).include?(connection.adapter_name.downcase) && ActiveRecord::VERSION::MAJOR >= 5
|
50
|
+
reorder("coalesce(#{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)}, '')", order)
|
51
|
+
else
|
52
|
+
reorder("(CASE WHEN #{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)} IS NULL THEN 0 ELSE 1 END), #{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)}", order)
|
53
|
+
end
|
89
54
|
}
|
55
|
+
scope :ordered_by_ancestry_and, Proc.new { |order| ordered_by_ancestry_and(order) }
|
56
|
+
scope :path_of, lambda { |object| to_node(object).path }
|
57
|
+
|
58
|
+
# Update descendants with new ancestry before save
|
59
|
+
before_save :update_descendants_with_new_ancestry
|
60
|
+
|
61
|
+
# Apply orphan strategy before destroy
|
62
|
+
before_destroy :apply_orphan_strategy
|
63
|
+
|
64
|
+
# Create ancestry column accessor and set to option or default
|
65
|
+
if options[:cache_depth]
|
66
|
+
# Create accessor for column name and set to option or default
|
67
|
+
self.cattr_accessor :depth_cache_column
|
68
|
+
self.depth_cache_column = options[:depth_cache_column] || :ancestry_depth
|
69
|
+
|
70
|
+
# Cache depth in depth cache column before save
|
71
|
+
before_validation :cache_depth
|
72
|
+
before_save :cache_depth
|
73
|
+
|
74
|
+
# Validate depth column
|
75
|
+
validates_numericality_of depth_cache_column, :greater_than_or_equal_to => 0, :only_integer => true, :allow_nil => false
|
76
|
+
end
|
77
|
+
|
78
|
+
# Create named scopes for depth
|
79
|
+
{:before_depth => '<', :to_depth => '<=', :at_depth => '=', :from_depth => '>=', :after_depth => '>'}.each do |scope_name, operator|
|
80
|
+
scope scope_name, lambda { |depth|
|
81
|
+
raise Ancestry::AncestryException.new("Named scope '#{scope_name}' is only available when depth caching is enabled.") unless options[:cache_depth]
|
82
|
+
where("#{depth_cache_column} #{operator} ?", depth)
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
after_touch :touch_ancestors_callback
|
87
|
+
after_destroy :touch_ancestors_callback
|
88
|
+
|
89
|
+
if ActiveRecord::VERSION::STRING >= '5.1.0'
|
90
|
+
after_save :touch_ancestors_callback, if: :saved_changes?
|
91
|
+
else
|
92
|
+
after_save :touch_ancestors_callback, if: :changed?
|
93
|
+
end
|
90
94
|
end
|
91
95
|
|
92
|
-
|
93
|
-
|
94
|
-
|
96
|
+
def acts_as_tree(*args)
|
97
|
+
return super if defined?(super)
|
98
|
+
has_ancestry(*args)
|
99
|
+
end
|
95
100
|
end
|
96
101
|
end
|
97
102
|
|
98
103
|
ActiveSupport.on_load :active_record do
|
99
|
-
|
100
|
-
class << ActiveRecord::Base
|
101
|
-
alias_method :acts_as_tree, :has_ancestry
|
102
|
-
end
|
103
|
-
end
|
104
|
+
send :extend, Ancestry::HasAncestry
|
104
105
|
end
|
@@ -7,22 +7,19 @@ module Ancestry
|
|
7
7
|
|
8
8
|
# Update descendants with new ancestry
|
9
9
|
def update_descendants_with_new_ancestry
|
10
|
-
#
|
11
|
-
|
12
|
-
#
|
13
|
-
|
14
|
-
# ...
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
descendant.
|
19
|
-
self.
|
20
|
-
|
21
|
-
/^#{self.child_ancestry}/,
|
22
|
-
if read_attribute(self.class.ancestry_column).blank? then id.to_s else "#{read_attribute self.class.ancestry_column }/#{id}" end
|
23
|
-
)
|
10
|
+
# If enabled and node is existing and ancestry was updated and the new ancestry is sane ...
|
11
|
+
if !ancestry_callbacks_disabled? && !new_record? && ancestry_changed? && sane_ancestry?
|
12
|
+
# ... for each descendant ...
|
13
|
+
unscoped_descendants.each do |descendant|
|
14
|
+
# ... replace old ancestry with new ancestry
|
15
|
+
descendant.without_ancestry_callbacks do
|
16
|
+
descendant.update_attribute(
|
17
|
+
self.ancestry_base_class.ancestry_column,
|
18
|
+
descendant.read_attribute(descendant.class.ancestry_column).gsub(
|
19
|
+
/^#{self.child_ancestry}/,
|
20
|
+
if ancestors? then "#{read_attribute self.class.ancestry_column }/#{id}" else id.to_s end
|
24
21
|
)
|
25
|
-
|
22
|
+
)
|
26
23
|
end
|
27
24
|
end
|
28
25
|
end
|
@@ -30,56 +27,47 @@ module Ancestry
|
|
30
27
|
|
31
28
|
# Apply orphan strategy
|
32
29
|
def apply_orphan_strategy
|
33
|
-
|
34
|
-
|
35
|
-
#
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
descendant.
|
30
|
+
if !ancestry_callbacks_disabled? && !new_record?
|
31
|
+
case self.ancestry_base_class.orphan_strategy
|
32
|
+
when :rootify # make all children root if orphan strategy is rootify
|
33
|
+
unscoped_descendants.each do |descendant|
|
34
|
+
descendant.without_ancestry_callbacks do
|
35
|
+
new_ancestry = if descendant.ancestry == child_ancestry
|
36
|
+
nil
|
37
|
+
else
|
38
|
+
descendant.ancestry.gsub(/^#{child_ancestry}\//, '')
|
42
39
|
end
|
40
|
+
descendant.update_attribute descendant.class.ancestry_column, new_ancestry
|
43
41
|
end
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
42
|
+
end
|
43
|
+
when :destroy # destroy all descendants if orphan strategy is destroy
|
44
|
+
unscoped_descendants.each do |descendant|
|
45
|
+
descendant.without_ancestry_callbacks do
|
46
|
+
descendant.destroy
|
50
47
|
end
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
48
|
+
end
|
49
|
+
when :adopt # make child elements of this node, child of its parent
|
50
|
+
descendants.each do |descendant|
|
51
|
+
descendant.without_ancestry_callbacks do
|
52
|
+
new_ancestry = descendant.ancestor_ids.delete_if { |x| x == self.id }.join("/")
|
53
|
+
# check for empty string if it's then set to nil
|
54
|
+
new_ancestry = nil if new_ancestry.empty?
|
55
|
+
descendant.update_attribute descendant.class.ancestry_column, new_ancestry || nil
|
60
56
|
end
|
61
|
-
# ... throw an exception if it has children and orphan strategy is restrict
|
62
|
-
elsif self.ancestry_base_class.orphan_strategy == :restrict
|
63
|
-
raise Ancestry::AncestryException.new('Cannot delete record because it has descendants.') unless is_childless?
|
64
57
|
end
|
58
|
+
when :restrict # throw an exception if it has children
|
59
|
+
raise Ancestry::AncestryException.new('Cannot delete record because it has descendants.') unless is_childless?
|
65
60
|
end
|
66
61
|
end
|
67
62
|
end
|
68
63
|
|
69
64
|
# Touch each of this record's ancestors
|
70
65
|
def touch_ancestors_callback
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
if self.ancestry_base_class.touch_ancestors
|
77
|
-
|
78
|
-
# Touch each of the old *and* new ancestors
|
79
|
-
self.class.where(id: (ancestor_ids + ancestor_ids_was).uniq).each do |ancestor|
|
80
|
-
ancestor.without_ancestry_callbacks do
|
81
|
-
ancestor.touch
|
82
|
-
end
|
66
|
+
if !ancestry_callbacks_disabled? && self.ancestry_base_class.touch_ancestors
|
67
|
+
# Touch each of the old *and* new ancestors
|
68
|
+
unscoped_current_and_previous_ancestors.each do |ancestor|
|
69
|
+
ancestor.without_ancestry_callbacks do
|
70
|
+
ancestor.touch
|
83
71
|
end
|
84
72
|
end
|
85
73
|
end
|
@@ -95,6 +83,11 @@ module Ancestry
|
|
95
83
|
|
96
84
|
# Ancestors
|
97
85
|
|
86
|
+
def ancestors?
|
87
|
+
# ancestor_ids.present?
|
88
|
+
read_attribute(self.ancestry_base_class.ancestry_column).present?
|
89
|
+
end
|
90
|
+
|
98
91
|
def ancestry_changed?
|
99
92
|
changed.include?(self.ancestry_base_class.ancestry_column.to_s)
|
100
93
|
end
|
@@ -108,8 +101,7 @@ module Ancestry
|
|
108
101
|
end
|
109
102
|
|
110
103
|
def ancestor_conditions
|
111
|
-
|
112
|
-
t[get_primary_key_column].in(ancestor_ids)
|
104
|
+
self.ancestry_base_class.ancestor_conditions(self)
|
113
105
|
end
|
114
106
|
|
115
107
|
def ancestors depth_options = {}
|
@@ -121,7 +113,13 @@ module Ancestry
|
|
121
113
|
end
|
122
114
|
|
123
115
|
def ancestor_ids_was
|
124
|
-
|
116
|
+
relevant_attributes = if ActiveRecord::VERSION::STRING >= '5.1.0'
|
117
|
+
saved_changes.transform_values(&:first)
|
118
|
+
else
|
119
|
+
changed_attributes
|
120
|
+
end
|
121
|
+
|
122
|
+
parse_ancestry_column(relevant_attributes[self.ancestry_base_class.ancestry_column.to_s])
|
125
123
|
end
|
126
124
|
|
127
125
|
def path_ids
|
@@ -129,8 +127,7 @@ module Ancestry
|
|
129
127
|
end
|
130
128
|
|
131
129
|
def path_conditions
|
132
|
-
|
133
|
-
t[get_primary_key_column].in(path_ids)
|
130
|
+
self.ancestry_base_class.path_conditions(self)
|
134
131
|
end
|
135
132
|
|
136
133
|
def path depth_options = {}
|
@@ -155,20 +152,20 @@ module Ancestry
|
|
155
152
|
write_attribute(self.ancestry_base_class.ancestry_column, if parent.nil? then nil else parent.child_ancestry end)
|
156
153
|
end
|
157
154
|
|
158
|
-
def parent_id=
|
159
|
-
self.parent =
|
155
|
+
def parent_id= new_parent_id
|
156
|
+
self.parent = new_parent_id.present? ? unscoped_find(new_parent_id) : nil
|
160
157
|
end
|
161
158
|
|
162
159
|
def parent_id
|
163
|
-
|
160
|
+
ancestor_ids.last if ancestors?
|
164
161
|
end
|
165
162
|
|
166
163
|
def parent
|
167
|
-
|
164
|
+
unscoped_find(parent_id) if ancestors?
|
168
165
|
end
|
169
166
|
|
170
167
|
def parent_id?
|
171
|
-
|
168
|
+
ancestors?
|
172
169
|
end
|
173
170
|
|
174
171
|
def parent_of?(node)
|
@@ -178,11 +175,11 @@ module Ancestry
|
|
178
175
|
# Root
|
179
176
|
|
180
177
|
def root_id
|
181
|
-
|
178
|
+
ancestors? ? ancestor_ids.first : id
|
182
179
|
end
|
183
180
|
|
184
181
|
def root
|
185
|
-
|
182
|
+
ancestors? ? unscoped_find(root_id) : self
|
186
183
|
end
|
187
184
|
|
188
185
|
def is_root?
|
@@ -197,8 +194,7 @@ module Ancestry
|
|
197
194
|
# Children
|
198
195
|
|
199
196
|
def child_conditions
|
200
|
-
|
201
|
-
t[get_ancestry_column].eq(child_ancestry)
|
197
|
+
self.ancestry_base_class.child_conditions(self)
|
202
198
|
end
|
203
199
|
|
204
200
|
def children
|
@@ -206,11 +202,11 @@ module Ancestry
|
|
206
202
|
end
|
207
203
|
|
208
204
|
def child_ids
|
209
|
-
children.
|
205
|
+
children.pluck(self.ancestry_base_class.primary_key)
|
210
206
|
end
|
211
207
|
|
212
208
|
def has_children?
|
213
|
-
self.children.exists?
|
209
|
+
self.children.exists?
|
214
210
|
end
|
215
211
|
alias_method :children?, :has_children?
|
216
212
|
|
@@ -226,8 +222,7 @@ module Ancestry
|
|
226
222
|
# Siblings
|
227
223
|
|
228
224
|
def sibling_conditions
|
229
|
-
|
230
|
-
t[get_ancestry_column].eq(read_attribute(self.ancestry_base_class.ancestry_column))
|
225
|
+
self.ancestry_base_class.sibling_conditions(self)
|
231
226
|
end
|
232
227
|
|
233
228
|
def siblings
|
@@ -235,7 +230,7 @@ module Ancestry
|
|
235
230
|
end
|
236
231
|
|
237
232
|
def sibling_ids
|
238
|
-
siblings.
|
233
|
+
siblings.pluck(self.ancestry_base_class.primary_key)
|
239
234
|
end
|
240
235
|
|
241
236
|
def has_siblings?
|
@@ -255,13 +250,7 @@ module Ancestry
|
|
255
250
|
# Descendants
|
256
251
|
|
257
252
|
def descendant_conditions
|
258
|
-
|
259
|
-
# rails has case sensitive matching.
|
260
|
-
if defined?(ActiveRecord.version) && ActiveRecord.version.to_s >= "5"
|
261
|
-
t[get_ancestry_column].matches("#{child_ancestry}/%", nil, true).or(t[get_ancestry_column].eq(child_ancestry))
|
262
|
-
else
|
263
|
-
t[get_ancestry_column].matches("#{child_ancestry}/%").or(t[get_ancestry_column].eq(child_ancestry))
|
264
|
-
end
|
253
|
+
self.ancestry_base_class.descendant_conditions(self)
|
265
254
|
end
|
266
255
|
|
267
256
|
def descendants depth_options = {}
|
@@ -269,7 +258,7 @@ module Ancestry
|
|
269
258
|
end
|
270
259
|
|
271
260
|
def descendant_ids depth_options = {}
|
272
|
-
descendants(depth_options).
|
261
|
+
descendants(depth_options).pluck(self.ancestry_base_class.primary_key)
|
273
262
|
end
|
274
263
|
|
275
264
|
def descendant_of?(node)
|
@@ -279,8 +268,7 @@ module Ancestry
|
|
279
268
|
# Subtree
|
280
269
|
|
281
270
|
def subtree_conditions
|
282
|
-
|
283
|
-
descendant_conditions.or(t[get_primary_key_column].eq(self.id))
|
271
|
+
self.ancestry_base_class.subtree_conditions(self)
|
284
272
|
end
|
285
273
|
|
286
274
|
def subtree depth_options = {}
|
@@ -288,7 +276,7 @@ module Ancestry
|
|
288
276
|
end
|
289
277
|
|
290
278
|
def subtree_ids depth_options = {}
|
291
|
-
subtree(depth_options).
|
279
|
+
subtree(depth_options).pluck(self.ancestry_base_class.primary_key)
|
292
280
|
end
|
293
281
|
|
294
282
|
# Callback disabling
|
@@ -323,26 +311,14 @@ module Ancestry
|
|
323
311
|
end
|
324
312
|
end
|
325
313
|
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
314
|
+
def unscoped_current_and_previous_ancestors
|
315
|
+
self.ancestry_base_class.unscoped do
|
316
|
+
self.ancestry_base_class.where id: (ancestor_ids + ancestor_ids_was).uniq
|
317
|
+
end
|
330
318
|
end
|
331
319
|
|
332
320
|
def unscoped_find id
|
333
321
|
self.ancestry_base_class.unscoped { self.ancestry_base_class.find(id) }
|
334
322
|
end
|
335
|
-
|
336
|
-
def get_arel_table
|
337
|
-
self.ancestry_base_class.arel_table
|
338
|
-
end
|
339
|
-
|
340
|
-
def get_primary_key_column
|
341
|
-
self.ancestry_base_class.primary_key.to_sym
|
342
|
-
end
|
343
|
-
|
344
|
-
def get_ancestry_column
|
345
|
-
self.ancestry_base_class.ancestry_column.to_sym
|
346
|
-
end
|
347
323
|
end
|
348
324
|
end
|