/
acts_as_nested_interval.rb
60 lines (48 loc) · 2.5 KB
/
acts_as_nested_interval.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
# Copyright (c) 2007, 2008 Pythonic Pty Ltd
# http://www.pythonic.com.au/
# Copyright (c) 2012 Nicolae Claudius
# https://github.com/clyfe
require 'acts_as_nested_interval/core_ext/integer'
require 'acts_as_nested_interval/version'
require 'acts_as_nested_interval/instance_methods'
require 'acts_as_nested_interval/class_methods'
# This act implements a nested-interval tree. You can find all descendants
# or all ancestors with just one select query. You can insert and delete
# records without a full table update.
module ActsAsNestedInterval
# The +options+ hash can include:
# * <tt>:foreign_key</tt> -- the self-reference foreign key column name (default :parent_id).
# * <tt>:scope_columns</tt> -- an array of columns to scope independent trees.
# * <tt>:lft_index</tt> -- whether to use functional index for lft (default false).
# * <tt>:virtual_root</tt> -- whether to compute root's interval as in an upper root (default false)
# * <tt>:dependent</tt> -- dependency between the parent node and children nodes (default :restrict)
def acts_as_nested_interval(options = {})
cattr_accessor :nested_interval_foreign_key
cattr_accessor :nested_interval_scope_columns
cattr_accessor :nested_interval_lft_index
cattr_accessor :nested_interval_dependent
cattr_accessor :virtual_root
self.virtual_root = !!options[:virtual_root]
self.nested_interval_foreign_key = options[:foreign_key] || :parent_id
self.nested_interval_scope_columns = Array(options[:scope_columns])
self.nested_interval_lft_index = options[:lft_index]
self.nested_interval_dependent = options[:dependent] || :restrict
belongs_to :parent, class_name: name, foreign_key: nested_interval_foreign_key
has_many :children, class_name: name, foreign_key: nested_interval_foreign_key,
dependent: nested_interval_dependent
scope :roots, -> { where(nested_interval_foreign_key => nil) }
if columns_hash["rgt"]
scope :preorder, -> { order('rgt DESC, lftp ASC') }
elsif columns_hash["rgtp"] && columns_hash["rgtq"]
scope :preorder, -> { order('1.0 * rgtp / rgtq DESC, lftp ASC') }
else
scope :preorder, -> { order('nested_interval_rgt(lftp, lftq) DESC, lftp ASC') }
end
before_create :create_nested_interval
before_destroy :destroy_nested_interval
before_update :update_nested_interval
include ActsAsNestedInterval::InstanceMethods
extend ActsAsNestedInterval::ClassMethods
end
end
ActiveRecord::Base.send :extend, ActsAsNestedInterval