<commit_before>module Toy
  module Attributes
    extend ActiveSupport::Concern
    include ActiveModel::AttributeMethods

    included do
      include Identity

      # blank suffix is no longer needed in 3.2+
      # open to suggestions on how to do this better
      if ActiveSupport::VERSION::MAJOR == 3 && ActiveSupport::VERSION::MINOR < 2
        attribute_method_suffix('')
      end

      attribute_method_suffix('=')
      attribute_method_suffix('?')
    end

    module ClassMethods
      def attributes
        @attributes ||= {}
      end

      def defaulted_attributes
        attributes.values.select(&:default?)
      end

      def persisted_attributes
        attributes.values.select { |attribute| attribute.persisted? }
      end

      def attribute(key, type, options = {})
        attribute = Attribute.new(self, key, type, options)
        define_attribute_methods [attribute.name]
        attribute
      end

      def attribute?(key)
        attributes.has_key?(key.to_s)
      end
    end

    def initialize(attrs={})
      initialize_attributes
      self.attributes = attrs
      write_attribute :id, self.class.next_key(self) unless id?
    end

    def id
      read_attribute(:id)
    end

    def attributes
      @attributes
    end

    def persisted_attributes
      {}.tap do |attrs|
        self.class.attributes.except('id').each do |name, attribute|
          next if attribute.virtual?
          value = attribute.to_store(read_attribute(attribute.name))
          next if value.nil?
          attrs[attribute.persisted_name] = value
        end
      end
    end

    def attributes=(attrs, *)
      return if attrs.nil?
      attrs.each do |key, value|
        if respond_to?("#{key}=")
          send("#{key}=", value)<commit_msg>Use class level persisted_attributes to generate instance persisted attributes.<commit_after>module Toy
  module Attributes
    extend ActiveSupport::Concern
    include ActiveModel::AttributeMethods

    included do
      include Identity

      # blank suffix is no longer needed in 3.2+
      # open to suggestions on how to do this better
      if ActiveSupport::VERSION::MAJOR == 3 && ActiveSupport::VERSION::MINOR < 2
        attribute_method_suffix('')
      end

      attribute_method_suffix('=')
      attribute_method_suffix('?')
    end

    module ClassMethods
      def attributes
        @attributes ||= {}
      end

      def defaulted_attributes
        attributes.values.select(&:default?)
      end

      def persisted_attributes
        attributes.values.select { |attribute| attribute.persisted? }
      end

      def attribute(key, type, options = {})
        attribute = Attribute.new(self, key, type, options)
        define_attribute_methods [attribute.name]
        attribute
      end

      def attribute?(key)
        attributes.has_key?(key.to_s)
      end
    end

    def initialize(attrs={})
      initialize_attributes
      self.attributes = attrs
      write_attribute :id, self.class.next_key(self) unless id?
    end

    def id
      read_attribute(:id)
    end

    def attributes
      @attributes
    end

    def persisted_attributes
      {}.tap do |attrs|
        self.class.persisted_attributes.each do |attribute|
          if (value = attribute.to_store(read_attribute(attribute.name)))
            attrs[attribute.persisted_name] = value
          end
        end
      end
    end

    def attributes=(attrs, *)
      return if attrs.nil?
      attrs.each do |key, value|
        if respond_to?("#{key}=")
          send("#{key}=", value)
{'fraction_non_alphanumeric': 0.08879551820728292, 'fraction_numerical': 0.002240896358543417, 'mean_word_length': 2.349906191369606, 'pattern_counts': {'":': 0, '<': 5, '<?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': '1510670', 'n_tokens_mistral': 989, 'n_tokens_neox': 951, 'n_words': 256}