ancestry 2.2.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 scope.where(options)
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
- class << ActiveRecord::Base
2
- def has_ancestry options = {}
3
- # Check options
4
- raise Ancestry::AncestryException.new("Options for has_ancestry must be in a hash.") unless options.is_a? Hash
5
- options.each do |key, value|
6
- unless [:ancestry_column, :orphan_strategy, :cache_depth, :depth_cache_column, :touch].include? key
7
- raise Ancestry::AncestryException.new("Unknown option for has_ancestry: #{key.inspect} => #{value.inspect}.")
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
- # Update descendants with new ancestry before save
65
- before_save :update_descendants_with_new_ancestry
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
- # Apply orphan strategy before destroy
68
- before_destroy :apply_orphan_strategy
17
+ # Save self as base class (for STI)
18
+ cattr_accessor :ancestry_base_class
19
+ self.ancestry_base_class = self
69
20
 
70
- # Create ancestry column accessor and set to option or default
71
- if options[:cache_depth]
72
- # Create accessor for column name and set to option or default
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
- # Cache depth in depth cache column before save
77
- before_validation :cache_depth
78
- before_save :cache_depth
25
+ # Include instance methods
26
+ include Ancestry::InstanceMethods
79
27
 
80
- # Validate depth column
81
- validates_numericality_of depth_cache_column, :greater_than_or_equal_to => 0, :only_integer => true, :allow_nil => false
82
- end
28
+ # Include dynamic class methods
29
+ extend Ancestry::ClassMethods
83
30
 
84
- # Create named scopes for depth
85
- {:before_depth => '<', :to_depth => '<=', :at_depth => '=', :from_depth => '>=', :after_depth => '>'}.each do |scope_name, operator|
86
- scope scope_name, lambda { |depth|
87
- raise Ancestry::AncestryException.new("Named scope '#{scope_name}' is only available when depth caching is enabled.") unless options[:cache_depth]
88
- where("#{depth_cache_column} #{operator} ?", depth)
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
- after_touch :touch_ancestors_callback
93
- after_destroy :touch_ancestors_callback
94
- after_save :touch_ancestors_callback, if: :changed?
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
- if not(ActiveRecord::Base.respond_to?(:acts_as_tree))
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
- # Skip this if callbacks are disabled
11
- unless ancestry_callbacks_disabled?
12
- # If node is not a new record and ancestry was updated and the new ancestry is sane ...
13
- if ancestry_changed? && !new_record? && sane_ancestry?
14
- # ... for each descendant ...
15
- unscoped_descendants.each do |descendant|
16
- # ... replace old ancestry with new ancestry
17
- descendant.without_ancestry_callbacks do
18
- descendant.update_attribute(
19
- self.ancestry_base_class.ancestry_column,
20
- descendant.read_attribute(descendant.class.ancestry_column).gsub(
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
- end
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
- # Skip this if callbacks are disabled
34
- unless ancestry_callbacks_disabled?
35
- # If this isn't a new record ...
36
- unless new_record?
37
- # ... make all children root if orphan strategy is rootify
38
- if self.ancestry_base_class.orphan_strategy == :rootify
39
- unscoped_descendants.each do |descendant|
40
- descendant.without_ancestry_callbacks do
41
- descendant.update_attribute descendant.class.ancestry_column, (if descendant.ancestry == child_ancestry then nil else descendant.ancestry.gsub(/^#{child_ancestry}\//, '') end)
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
- # ... destroy all descendants if orphan strategy is destroy
45
- elsif self.ancestry_base_class.orphan_strategy == :destroy
46
- unscoped_descendants.each do |descendant|
47
- descendant.without_ancestry_callbacks do
48
- descendant.destroy
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
- # ... make child elements of this node, child of its parent if orphan strategy is adopt
52
- elsif self.ancestry_base_class.orphan_strategy == :adopt
53
- descendants.each do |descendant|
54
- descendant.without_ancestry_callbacks do
55
- new_ancestry = descendant.ancestor_ids.delete_if { |x| x == self.id }.join("/")
56
- # check for empty string if it's then set to nil
57
- new_ancestry = nil if new_ancestry.empty?
58
- descendant.update_attribute descendant.class.ancestry_column, new_ancestry || nil
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
- # Skip this if callbacks are disabled
73
- unless ancestry_callbacks_disabled?
74
-
75
- # Only touch if the option is enabled
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
- t = get_arel_table
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
- parse_ancestry_column(changed_attributes[self.ancestry_base_class.ancestry_column.to_s])
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
- t = get_arel_table
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= parent_id
159
- self.parent = if parent_id.blank? then nil else unscoped_find(parent_id) end
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
- if ancestor_ids.empty? then nil else ancestor_ids.last end
160
+ ancestor_ids.last if ancestors?
164
161
  end
165
162
 
166
163
  def parent
167
- if parent_id.blank? then nil else unscoped_find(parent_id) end
164
+ unscoped_find(parent_id) if ancestors?
168
165
  end
169
166
 
170
167
  def parent_id?
171
- parent_id.present?
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
- if ancestor_ids.empty? then id else ancestor_ids.first end
178
+ ancestors? ? ancestor_ids.first : id
182
179
  end
183
180
 
184
181
  def root
185
- if root_id == id then self else unscoped_find(root_id) end
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
- t = get_arel_table
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.select(self.ancestry_base_class.primary_key).map(&self.ancestry_base_class.primary_key.to_sym)
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
- t = get_arel_table
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.select(self.ancestry_base_class.primary_key).collect(&self.ancestry_base_class.primary_key.to_sym)
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
- t = get_arel_table
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).select(self.ancestry_base_class.primary_key).collect(&self.ancestry_base_class.primary_key.to_sym)
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
- t = get_arel_table
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).select(self.ancestry_base_class.primary_key).collect(&self.ancestry_base_class.primary_key.to_sym)
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
- # Validates the ancestry, but can also be applied if validation is bypassed to determine if children should be affected
327
- def sane_ancestry?
328
- ancestry_value = read_attribute(self.ancestry_base_class.ancestry_column)
329
- ancestry_value.nil? || (ancestry_value.to_s =~ Ancestry::ANCESTRY_PATTERN && !ancestor_ids.include?(self.id))
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