<commit_before>require 'datev/field'

module Datev
  class Base
    class << self
      attr_accessor :fields
    end

    attr_accessor :attributes

    def self.field(name, type, options={}, &block)
      self.fields ||= []

      # Check if there is already a field with the same name
      if self.fields.find { |f| f.name == name }
        raise ArgumentError.new("Field '#{name}' already exists")
      end

      self.fields << Field.new(name, type, options, &block)
    end

    def initialize(attributes)
      self.attributes = {}

      raise ArgumentError.new('Hash required') unless attributes.is_a?(Hash)

      # Check existing names and set value (if valid)
      attributes.each_pair do |name,value|
        unless field = self.class.fields.find { |f| f.name == name }
          raise ArgumentError.new("Field '#{name}' not found")
        end

        field.validate!(value)
        self.attributes[name] = value
      end

      # Check for missing values
      self.class.fields.select(&:required?).each do |field|
        if attributes[field.name].nil?
          raise ArgumentError.new("Value for field '#{field.name}' is required but missing")
        end
      end
    end

    def [](name)
      field = self.class.fields.find { |f| f.name == name }
      raise ArgumentError.new("Field '#{name}' not found") unless field

      attributes[field.name]
    end

    def output(context=nil)
      self.class.fields.map do |field|
        value = attributes[field.name]
        field.output(value, context)<commit_msg>Base refactoring<commit_after>require 'datev/field'

module Datev
  class Base
    class << self
      attr_accessor :fields
    end

    attr_accessor :attributes

    def self.field(name, type, options={}, &block)
      self.fields ||= []

      # Check if there is already a field with the same name
      if field_by_name(name)
        raise ArgumentError.new("Field '#{name}' already exists")
      end

      self.fields << Field.new(name, type, options, &block)
    end

    def self.field_by_name(name)
      self.fields.find { |f| f.name == name }
    end

    def initialize(attributes)
      self.attributes = {}

      raise ArgumentError.new('Hash required') unless attributes.is_a?(Hash)

      # Check existing names and set value (if valid)
      attributes.each_pair do |name,value|
        unless field = self.class.field_by_name(name)
          raise ArgumentError.new("Field '#{name}' not found")
        end

        field.validate!(value)
        self.attributes[name] = value
      end

      # Check for missing values
      self.class.fields.select(&:required?).each do |field|
        if attributes[field.name].nil?
          raise ArgumentError.new("Value for field '#{field.name}' is required but missing")
        end
      end
    end

    def [](name)
      field = self.class.field_by_name(name)
      raise ArgumentError.new("Field '#{name}' not found") unless field

      attributes[field.name]
    end

    def output(context=nil)
      self.class.fields.map do |field|
        value = attributes[field.name]
        field.output(value, context)
{'fraction_non_alphanumeric': 0.112463953860942, 'fraction_numerical': 0.0, 'mean_word_length': 2.5, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 3, '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': '2082144', 'n_tokens_mistral': 915, 'n_tokens_neox': 888, 'n_words': 254}