<commit_before>module ActsAsManyTrees
  module Base
    extend ActiveSupport::Concern

    included do
    end

    module ClassMethods
      def acts_as_many_trees(options = {})
        class_attribute :hierarchy_class
        self.hierarchy_class = (name+'Hierarchy').constantize
        include ActsAsManyTrees::InstanceMethods
        extend ActsAsManyTrees::ClassMethods
        hierarchy_class.send :include,ActsAsManyTrees::HierarchyTable
      end
    end

  end
  module ClassMethods
    def hierarchy_table_name
      hierarchy_class.table_name
    end
  end
  module InstanceMethods
    extend ActiveSupport::Concern
    included do
      has_many :unscoped_descendant_links,
        ->{order(:position)},
        class_name:hierarchy_class.to_s,
        foreign_key: 'ancestor_id',
        dependent: :delete_all,
        inverse_of: :unscoped_ancestor

      has_many :unscoped_ancestor_links,
        ->{order(:position)},
        class_name: hierarchy_class.to_s,
        foreign_key: 'descendant_id',
        dependent: :delete_all,
        inverse_of: :unscoped_descendant

      has_many :unscoped_ancestors,through: :unscoped_ancestor_links
      has_many :unscoped_descendants,  {:through=>:unscoped_descendant_links, :source=>:unscoped_descendant}
      has_many :item_siblings,  
        {:through=>:unscoped_ancestor_links, 
         :source=>:item_siblings}
      has_many :siblings_before,
        ->{where('unscoped_ancestor_links_siblings_before_join.position > item_hierarchies.position').where('unscoped_ancestor_links_siblings_before_join.generation=1')},
        {:through=>:unscoped_ancestor_links, 
         :source=>:item_siblings}
      has_many :siblings_after,
        ->{where('unscoped_ancestor_links_siblings_after_join.position < item_hierarchies.position').where('unscoped_ancestor_links_siblings_after_join.generation=1')},
        {:through=>:unscoped_ancestor_links, 
         :source=>:item_siblings}

      scope :roots , ->(hierarchy=''){
        on = Arel::Nodes::On.new(Arel::Nodes::Equality.new(arel_table[:id],hierarchy_class.arel_table[:descendant_id])
                                 .and(hierarchy_class.arel_table[:hierarchy_scope].eq(hierarchy))
                                )
        outer_join = Arel::Nodes::OuterJoin.new(hierarchy_class.arel_table,on)
        joins(outer_join).merge(hierarchy_class.where(generation: 0))
      }
      scope :scope1,->(rec) do
        joins(:unscoped_ancestor_links).joins(:unscoped_descendant_links).on('unscoped_descendant_links.ancestor_id = item_hierarchies.ancestor_id')
      end
    end
    delegate :hierarchy_class, to: :class
    def parent=(inpt_parent)
      if inpt_parent.is_a?(Hash)
         new_parent=inpt_parent[:new_parent]
         after_node=inpt_parent[:after_node]
         before_node=inpt_parent[:before_node]
         hierarchy_scope=inpt_parent[:hierarchy_scope] || ''
      else
        new_parent=inpt_parent
        hierarchy_scope = ''
      end  
      hierarchy_class.set_parent_of(self,new_parent,hierarchy_scope,after_node,before_node)
    end

    def set_parent(new_parent,hierarchy_scope='')
      hierarchy_class.set_parent_of(self,new_parent,hierarchy_scope)
    end

    def add_child(new_child,hierarchy_scope='')
      hierarchy_class.set_parent_of(new_child,self,hierarchy_scope)
    end

    def parent(hierarchy_scope='')
      ancestors(hierarchy_scope).where('generation=1').first
    end

    def children(hierarchy_scope='')
      descendants(hierarchy_scope).where('generation=1')
    end

#    def siblings(hierarchy_scope='')
#        parent(hierarchy_scope).children(hierarchy_scope).where.not(id: id)
#    end
#
#    def self_and_siblings(hierarchy_scope='')
##        parent(hierarchy_scope).children(hierarchy_scope)
#      self.class.joins(hierarchy_class).merge(hierarchy_class.self_and_siblings(self,hierarchy_scope))
#    end


    def ancestors(hierarchy='')
      unscoped_ancestors.merge(hierarchy_class.scope_hierarchy(hierarchy))
    end

    def descendants(hierarchy='')
      unscoped_descendants.merge(hierarchy_class.scope_hierarchy(hierarchy))
    end
  end

end
ActiveRecord::Base.send :include, ActsAsManyTrees::Base<commit_msg>setting a new parent now changes the position correctly<commit_after>module ActsAsManyTrees
  module Base
    extend ActiveSupport::Concern

    included do
    end

    module ClassMethods
      def acts_as_many_trees(options = {})
        class_attribute :hierarchy_class
        self.hierarchy_class = (name+'Hierarchy').constantize
        include ActsAsManyTrees::InstanceMethods
        extend ActsAsManyTrees::ClassMethods
        hierarchy_class.send :include,ActsAsManyTrees::HierarchyTable
      end
    end

  end
  module ClassMethods
    def hierarchy_table_name
      hierarchy_class.table_name
    end
  end
  module InstanceMethods
    extend ActiveSupport::Concern
    included do
      has_many :unscoped_descendant_links,
        ->{order(:position)},
        class_name:hierarchy_class.to_s,
        foreign_key: 'ancestor_id',
        dependent: :delete_all,
        inverse_of: :unscoped_ancestor

      has_many :unscoped_ancestor_links,
        ->{order(:position)},
        class_name: hierarchy_class.to_s,
        foreign_key: 'descendant_id',
        dependent: :delete_all,
        inverse_of: :unscoped_descendant

      has_many :unscoped_ancestors,through: :unscoped_ancestor_links
      has_many :unscoped_descendants,  {:through=>:unscoped_descendant_links, :source=>:unscoped_descendant}
      has_many :self_and_siblings,  
        {:through=>:unscoped_ancestor_links, 
         :source=>:item_siblings}
      has_many :siblings_before,
        ->{where('unscoped_ancestor_links_siblings_before_join.position > item_hierarchies.position').where('unscoped_ancestor_links_siblings_before_join.generation=1')},
        {:through=>:unscoped_ancestor_links, 
         :source=>:item_siblings}
      has_many :siblings_after,
        ->{where('unscoped_ancestor_links_siblings_after_join.position < item_hierarchies.position').where('unscoped_ancestor_links_siblings_after_join.generation=1')},
        {:through=>:unscoped_ancestor_links, 
         :source=>:item_siblings}

      scope :roots , ->(hierarchy=''){
        on = Arel::Nodes::On.new(Arel::Nodes::Equality.new(arel_table[:id],hierarchy_class.arel_table[:descendant_id])
                                 .and(hierarchy_class.arel_table[:hierarchy_scope].eq(hierarchy))
                                )
        outer_join = Arel::Nodes::OuterJoin.new(hierarchy_class.arel_table,on)
        joins(outer_join).merge(hierarchy_class.where(generation: 0))
      }
    end
    delegate :hierarchy_class, to: :class
    def parent=(inpt_parent)
      if inpt_parent.is_a?(Hash)
         new_parent=inpt_parent[:new_parent]
         after_node=inpt_parent[:after_node] 
         before_node=inpt_parent[:before_node] 
         hierarchy_scope=inpt_parent[:hierarchy_scope] || ''
      else
        new_parent=inpt_parent
        after_node=inpt_parent.children.last unless inpt_parent.nil?
        before_node=inpt_parent.next_sibling unless inpt_parent.nil?
        hierarchy_scope = ''
      end  
      hierarchy_class.set_parent_of(self,new_parent,hierarchy_scope,after_node,before_node)
    end

    def set_parent(new_parent,hierarchy_scope='')
      hierarchy_class.set_parent_of(self,new_parent,hierarchy_scope)
    end

    def add_child(new_child,hierarchy_scope='')
      hierarchy_class.set_parent_of(new_child,self,hierarchy_scope)
    end

    def parent(hierarchy_scope='')
      ancestors(hierarchy_scope).where('generation=1').first
    end

    def children(hierarchy_scope='')
      descendants(hierarchy_scope).where('generation=1')
    end

    def ancestors(hierarchy='')
      unscoped_ancestors.merge(hierarchy_class.scope_hierarchy(hierarchy))
    end

    def descendants(hierarchy='')
      unscoped_descendants.merge(hierarchy_class.scope_hierarchy(hierarchy))
    end
    
    def siblings
      self_and_siblings.where.not(id: id)
    end

    def previous_sibling
      siblings_before.last
    end

    def next_sibling
      siblings_after.first
    end

  end

end
ActiveRecord::Base.send :include, ActsAsManyTrees::Base
{'fraction_non_alphanumeric': 0.09537677466326902, 'fraction_numerical': 0.001334789467297658, 'mean_word_length': 3.6512415349887135, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3805160', 'n_tokens_mistral': 2794, 'n_tokens_neox': 2768, 'n_words': 324}