<commit_before>module Beatport
  
  class Item < OpenStruct
    @@associations = {}
        
    def initialize(data = {})
      raise ArgumentError, "Invalid data passed to Item.new" unless data.is_a?(Hash)
            
      # OpenStruct doesn't like ids in its data, so we store it after the call to super
      id = data.delete('id')
      
      @@associations.each do |k, v|
        associate(data, k, v[:list], v[:klass])
      end
      
      super(data)
      
      @table['id'] = id if id
    end
    
    def id
      @table['id']
    end
    
    # Allow treating the item as a hash
    def [](key)
      send(key) if respond_to?(key)
    end
    
    def associate(data, var, many = false, klass = Item)
      a = data.delete(var.to_s)
      
      return unless a
      
      if many
        instance_variable_set(:"@#{var}", a.map { |g| klass.new(g) })
      else
        instance_variable_set(:"@#{var}", klass.new(a))
      end
    end
    
    def self.has_one(var, klass)
      self.send(:attr_reader, var)

      @@associations[var] = {:list => false, :klass => klass}
    end
    
    def self.has_many(var, klass)
      self.send(:attr_reader, var)

      @@associations[var] = {:list => true, :klass => klass}
    end
    
  end
end<commit_msg>Properly handle empty associations that show up as empty arrays<commit_after>module Beatport
  
  class Item < OpenStruct
    @@associations = {}
        
    def initialize(data = {})
      raise ArgumentError, "Invalid data passed to Item.new: #{data.inspect}" unless data.is_a?(Hash)
            
      # OpenStruct doesn't like ids in its data, so we store it after the call to super
      id = data.delete('id')
      
      @@associations.each do |k, v|
        associate(data, k, v[:list], v[:klass])
      end
      
      super(data)
      
      @table['id'] = id if id
    end
    
    def id
      @table['id']
    end
    
    # Allow treating the item as a hash
    def [](key)
      send(key) if respond_to?(key)
    end
    
    def associate(data, var, many = false, klass = Item)
      a = data.delete(var.to_s)
      
      return unless a
      
      if many
        a.map! { |g| klass.new(g) }
      elsif a.is_a?(Hash)
        a = klass.new(a)
      elsif a == []
        # In some cases, when there's no data returned for an association it'll be an empty array instead of a hash
        a = nil
      else
        raise ArgumentError, "Invalid data for association: #{a.inspect}"
      end
      
      instance_variable_set(:"@#{var}", a)
      
    end
    
    def self.has_one(var, klass)
      self.send(:attr_reader, var)

      @@associations[var] = {:list => false, :klass => klass}
    end
    
    def self.has_many(var, klass)
      self.send(:attr_reader, var)

      @@associations[var] = {:list => true, :klass => klass}
    end
    
  end
end
{'fraction_non_alphanumeric': 0.11855489301999299, 'fraction_numerical': 0.0, 'mean_word_length': 1.9432404540763675, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, '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': '3058074', 'n_tokens_mistral': 926, 'n_tokens_neox': 937, 'n_words': 271}