<commit_before>require 'active_support/concern'
require 'active_support/core_ext/array/extract_options'
require 'active_support/core_ext/class/attribute'
require 'active_support/core_ext/class/subclasses'
require 'active_support/core_ext/string/inflections'

module GQL
  module HasFields
    extend ActiveSupport::Concern

    included do
      class_attribute :fields, :field_proc, instance_accessor: false, instance_predicate: false
      self.fields = {}
    end

    module ClassMethods
      def add_field(id, *args, &block)
        remove_field id

        id          = id.to_sym
        options     = args.extract_options!
        type        = options.delete(:type) || Field
        proc        = args.shift || block || proc_for_field(id)
        const_name  = const_name_for_field(id)
        field_class = build_field_class(type, id, proc, options)

        send :remove_const, const_name if const_defined?(const_name, false)

        field_class.tap do |fc|
          const_set const_name, fc
          self.fields = fields.merge(id => fc)
          descendants.each { |f| f.fields[id] = fc }
        end
      end

      alias :field :add_field

      def remove_field(id)
        id = id.to_sym
        const_name = const_name_for_field(id)

        [self, *descendants].each do |f|
          next unless f.has_field? id

          f.send :remove_const, const_name if f.const_defined?(const_name, false)
          f.fields.delete id
        end
      end

      def has_field?(id)
        fields.has_key? id.to_sym
      end

      def cursor(id_or_proc)
        id = id_or_proc.is_a?(Proc) ? nil : id_or_proc<commit_msg>refactor add_field even more more<commit_after>require 'active_support/concern'
require 'active_support/core_ext/array/extract_options'
require 'active_support/core_ext/class/attribute'
require 'active_support/core_ext/class/subclasses'
require 'active_support/core_ext/string/inflections'

module GQL
  module HasFields
    extend ActiveSupport::Concern

    included do
      class_attribute :fields, :field_proc, instance_accessor: false, instance_predicate: false
      self.fields = {}
    end

    module ClassMethods
      def add_field(id, *args, &block)
        remove_field id

        id      = id.to_sym
        options = args.extract_options!
        type    = options.delete(:type) || Field
        proc    = args.shift || block || proc_for_field(id)

        build_field_class(type, id, proc, options).tap do |field_class|
          const_set const_name_for_field(id), field_class

          [self, *descendants].each do |f|
            f.fields = f.fields.merge(id => field_class)
          end
        end
      end

      alias :field :add_field

      def remove_field(id)
        id = id.to_sym
        const_name = const_name_for_field(id)

        [self, *descendants].each do |f|
          next unless f.has_field? id

          f.send :remove_const, const_name if f.const_defined?(const_name, false)
          f.fields.delete id
        end
      end

      def has_field?(id)
        fields.has_key? id.to_sym
      end

      def cursor(id_or_proc)
        id = id_or_proc.is_a?(Proc) ? nil : id_or_proc
{'fraction_non_alphanumeric': 0.08751974723538705, 'fraction_numerical': 0.0, 'mean_word_length': 2.502212389380531, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, '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': '3671143', 'n_tokens_mistral': 1012, 'n_tokens_neox': 989, 'n_words': 218}