<commit_before>module ActsAsNestedInterval
  module InstanceMethods
    extend ActiveSupport::Concern
    
    # selectively define #descendants according to table features
    included do
      
      if columns_hash["lft"]
        
        def descendants
          quoted_table_name = self.class.quoted_table_name
          nested_interval_scope.where <<-SQL
              #{lftp} < #{quoted_table_name}.lftp AND 
              #{quoted_table_name}.lft BETWEEN #{1.0 * lftp / lftq} AND #{1.0 * rgtp / rgtq}
          SQL
        end
        
      elsif nested_interval_lft_index
        
        def descendants
          quoted_table_name = self.class.quoted_table_name
          nested_interval_scope.where <<-SQL
              #{lftp} < #{quoted_table_name}.lftp AND 
              1.0 * #{quoted_table_name}.lftp / #{quoted_table_name}.lftq BETWEEN 
                #{1.0 * lftp / lftq} AND
                #{1.0 * rgtp / rgtq}
          SQL
        end
        
      elsif connection.adapter_name == "MySQL"
        
        def descendants
          quoted_table_name = self.class.quoted_table_name
          nested_interval_scope.where <<-SQL
              ( #{quoted_table_name}.lftp != #{rgtp} OR 
                #{quoted_table_name}.lftq != #{rgtq}
              ) AND
              #{quoted_table_name}.lftp BETWEEN 
                1 + #{quoted_table_name}.lftq * #{lftp} DIV #{lftq} AND 
                #{quoted_table_name}.lftq * #{rgtp} DIV #{rgtq}
          SQL
        end
        
      else
        
        def descendants
          quoted_table_name = self.class.quoted_table_name
          nested_interval_scope.where <<-SQL
              ( #{quoted_table_name}.lftp != #{rgtp} OR
                #{quoted_table_name}.lftq != #{rgtq}
              ) AND
              #{quoted_table_name}.lftp BETWEEN
                1 + #{quoted_table_name}.lftq * CAST(#{lftp} AS BIGINT) / #{lftq} AND
                #{quoted_table_name}.lftq * CAST(#{rgtp} AS BIGINT) / #{rgtq}
          SQL
        end
        
      end
      
    end
    
    def set_nested_interval(lftp, lftq)
      self.lftp, self.lftq = lftp, lftq
      self.rgtp = rgtp if has_attribute?(:rgtp)
      self.rgtq = rgtq if has_attribute?(:rgtq)
      self.lft = lft if has_attribute?(:lft)
      self.rgt = rgt if has_attribute?(:rgt)
    end
    
    def set_nested_interval_for_top
      if self.class.virtual_root
        set_nested_interval(*next_root_lft)
      else
        set_nested_interval 0, 1
      end
    end

    # Creates record.
    def create_nested_interval
      if read_attribute(nested_interval_foreign_key).nil?
        set_nested_interval_for_top
      else
        set_nested_interval *parent.lock!.next_child_lft
      end
    end

    # Destroys record.
    def destroy_nested_interval
      lock! rescue nil
    end

    def nested_interval_scope
      conditions = {}
      nested_interval_scope_columns.each do |column_name|
        conditions[column_name] = send(column_name)
      end
      self.class.where conditions
    end

    # Updates record, updating descendants if parent association updated,
    # in which case caller should first acquire table lock.
    def update_nested_interval
      changed = send(:"#{nested_interval_foreign_key}_changed?")
      if !changed
        db_self = self.class.find(id, :lock => true)
        write_attribute(nested_interval_foreign_key, db_self.read_attribute(nested_interval_foreign_key))
        set_nested_interval db_self.lftp, db_self.lftq
      else
        # No locking in this case -- caller should have acquired table lock.
        update_nested_interval_move
      end
    end
    
    def update_nested_interval_move
      begin
        db_self = self.class.find(id)
        db_parent = self.class.find(read_attribute(nested_interval_foreign_key))
        if db_self.ancestor_of?(db_parent)
          errors.add nested_interval_foreign_key, "is descendant"
          raise ActiveRecord::RecordInvalid, self
        end
      rescue ActiveRecord::RecordNotFound => e # root
      end
      
      if read_attribute(nested_interval_foreign_key).nil? # root move
        set_nested_interval_for_top
      else # child move
        set_nested_interval *parent.next_child_lft
      end
      cpp = db_self.lftq * rgtp - db_self.rgtq * lftp
      cpq = db_self.rgtp * lftp - db_self.lftp * rgtp
      cqp = db_self.lftq * rgtq - db_self.rgtq * lftq
      cqq = db_self.rgtp * lftq - db_self.lftp * rgtq

      updates = {}
      vars = Set.new
      mysql = ["MySQL", "Mysql2"].include?(connection.adapter_name)
      var = ->(v) { mysql ? vars.add?(v) ? "(@#{v} := #{v})" : "@#{v}" : v }
      multiply = ->(c, b) { "#{c} * #{var.(b)}" }
      add = ->(a, b) { "#{a} + #{b}" }
      one = sprintf("%#.30f", 1)
      divide = ->(p, q) { "#{one} * (#{p}) / (#{q})" }

      if has_attribute?(:rgtp) && has_attribute?(:rgtq)<commit_msg>Fir problem with attr_readonly for parent foreign key<commit_after>module ActsAsNestedInterval
  module InstanceMethods
    extend ActiveSupport::Concern
    
    # selectively define #descendants according to table features
    included do
      
      if columns_hash["lft"]
        
        def descendants
          quoted_table_name = self.class.quoted_table_name
          nested_interval_scope.where <<-SQL
              #{lftp} < #{quoted_table_name}.lftp AND 
              #{quoted_table_name}.lft BETWEEN #{1.0 * lftp / lftq} AND #{1.0 * rgtp / rgtq}
          SQL
        end
        
      elsif nested_interval_lft_index
        
        def descendants
          quoted_table_name = self.class.quoted_table_name
          nested_interval_scope.where <<-SQL
              #{lftp} < #{quoted_table_name}.lftp AND 
              1.0 * #{quoted_table_name}.lftp / #{quoted_table_name}.lftq BETWEEN 
                #{1.0 * lftp / lftq} AND
                #{1.0 * rgtp / rgtq}
          SQL
        end
        
      elsif connection.adapter_name == "MySQL"
        
        def descendants
          quoted_table_name = self.class.quoted_table_name
          nested_interval_scope.where <<-SQL
              ( #{quoted_table_name}.lftp != #{rgtp} OR 
                #{quoted_table_name}.lftq != #{rgtq}
              ) AND
              #{quoted_table_name}.lftp BETWEEN 
                1 + #{quoted_table_name}.lftq * #{lftp} DIV #{lftq} AND 
                #{quoted_table_name}.lftq * #{rgtp} DIV #{rgtq}
          SQL
        end
        
      else
        
        def descendants
          quoted_table_name = self.class.quoted_table_name
          nested_interval_scope.where <<-SQL
              ( #{quoted_table_name}.lftp != #{rgtp} OR
                #{quoted_table_name}.lftq != #{rgtq}
              ) AND
              #{quoted_table_name}.lftp BETWEEN
                1 + #{quoted_table_name}.lftq * CAST(#{lftp} AS BIGINT) / #{lftq} AND
                #{quoted_table_name}.lftq * CAST(#{rgtp} AS BIGINT) / #{rgtq}
          SQL
        end
        
      end
      
    end
    
    def set_nested_interval(lftp, lftq)
      self.lftp, self.lftq = lftp, lftq
      self.rgtp = rgtp if has_attribute?(:rgtp)
      self.rgtq = rgtq if has_attribute?(:rgtq)
      self.lft = lft if has_attribute?(:lft)
      self.rgt = rgt if has_attribute?(:rgt)
    end
    
    def set_nested_interval_for_top
      if self.class.virtual_root
        set_nested_interval(*next_root_lft)
      else
        set_nested_interval 0, 1
      end
    end

    # Creates record.
    def create_nested_interval
      if read_attribute(nested_interval_foreign_key).nil?
        set_nested_interval_for_top
      else
        set_nested_interval *parent.lock!.next_child_lft
      end
    end

    # Destroys record.
    def destroy_nested_interval
      lock! rescue nil
    end

    def nested_interval_scope
      conditions = {}
      nested_interval_scope_columns.each do |column_name|
        conditions[column_name] = send(column_name)
      end
      self.class.where conditions
    end

    # Updates record, updating descendants if parent association updated,
    # in which case caller should first acquire table lock.
    def update_nested_interval
      changed = send(:"#{nested_interval_foreign_key}_changed?")
      if !changed
        db_self = self.class.find(id, :lock => true)
        write_attribute(nested_interval_foreign_key, db_self.read_attribute(nested_interval_foreign_key))
        set_nested_interval db_self.lftp, db_self.lftq
      else
        # No locking in this case -- caller should have acquired table lock.
        update_nested_interval_move
      end
    end
    
    # Rewrite method
    def update_nested_interval_move
      return if self.class.readonly_attributes.include?(nested_interval_foreign_key.to_sym) # Fix issue #9
      begin
        db_self = self.class.find(id)
        db_parent = self.class.find(read_attribute(nested_interval_foreign_key))
        if db_self.ancestor_of?(db_parent)
          errors.add nested_interval_foreign_key, "is descendant"
          raise ActiveRecord::RecordInvalid, self
        end
      rescue ActiveRecord::RecordNotFound => e # root
      end
      
      if read_attribute(nested_interval_foreign_key).nil? # root move
        set_nested_interval_for_top
      else # child move
        set_nested_interval *parent.next_child_lft
      end
      cpp = db_self.lftq * rgtp - db_self.rgtq * lftp
      cpq = db_self.rgtp * lftp - db_self.lftp * rgtp
      cqp = db_self.lftq * rgtq - db_self.rgtq * lftq
      cqq = db_self.rgtp * lftq - db_self.lftp * rgtq

      updates = {}
      vars = Set.new
      mysql = ["MySQL", "Mysql2"].include?(connection.adapter_name)
      var = ->(v) { mysql ? vars.add?(v) ? "(@#{v} := #{v})" : "@#{v}" : v }
      multiply = ->(c, b) { "#{c} * #{var.(b)}" }
      add = ->(a, b) { "#{a} + #{b}" }
      one = sprintf("%#.30f", 1)
      divide = ->(p, q) { "#{one} * (#{p}) / (#{q})" }

      if has_attribute?(:rgtp) && has_attribute?(:rgtq)
{'fraction_non_alphanumeric': 0.09997996393508315, 'fraction_numerical': 0.003706672009617311, 'mean_word_length': 2.092627013630731, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '667549', 'n_tokens_mistral': 3374, 'n_tokens_neox': 3279, 'n_words': 662}