module Customize module Inherited def self.included base base.extend ClassMethods base.has_one :inherit_node, :class_name=>Customize::InheritNode.name, :as=>:node, :dependent=>:destroy base.after_create { |object| object.create_inherit_node :left=>0, :right=>1 } base.before_destroy { |object| raise 'object should not have children when destroy' if object.inherit_node.children.size > 0 } end module ClassMethods end def inherit parent raise 'should be save first' if self.new_record? raise 'should be same class' if self.class != parent.class inherit_node.parent_id = parent.inherit_node.id right = parent.inherit_node.right InheritNode.where("right >= ?", inherit_node.left).update_all("right = right+2") inherit_node.left = right inherit_node.right = right + 1 inherit_node.save end def ascent_ids @ascent_ids ||= InheritNode.where("left < :left and right > :right and node_type = :type", :left=>inherit_node.left, :right=>inherit_node.right, :type=>self.class.name).pluck(:node_id) end def descent_ids r = InheritNode.where("left > :left and right < :right and node_type = :type", :left=>inherit_node.left, :right=>inherit_node.right, :type=>self.class.name) r.pluck(:node_id) end def ascents self.class.find ascent_ids end end end