<commit_before>module Nestling
  class Base
    attr_reader :client

    METHOD_PREFIX = ""
    METHODS       = {}

    def initialize(client)
      @client = client
    end

    def method_missing(meth, *args, &block)
      unless method = self.class::METHODS[meth]
        return super(meth, *args, &block)
      end

      opts  = args[0] || {}
      key   = meth.to_s
      query = self.class::METHOD_PREFIX + key

      resp    = get(query, options(opts))["response"]
      payload = resp[method[:key] || key]

      if method[:collection]
        Collection.new(resp["total"], resp["start"],
                       resp["session_id"]).tap do |c|
          payload.each { |h| c << convert(h) }
        end
      else
        convert(payload)
      end
    end

    private

    def convert(hash)
      hash = Hash.new(hash)

      hash.each do |key, value|
        if value.kind_of?(String) &&
          value.match(/\d{4}(-\d\d){2}T\d{2}(:\d\d){2}/)
          hash[key] = DateTime.parse(value)
        elsif value.kind_of?(::Hash)
          hash[key] = convert(value)
        end
      end
    end

    def options(opts)
      opts
    end

    def get(*args)
      @client.get(*args)
    end
  end
end
<commit_msg>Use dynamic method generation instead of #method_missing.<commit_after>module Nestling
  class Base
    attr_reader :client

    METHOD_PREFIX = ""
    METHODS       = {}

    class << self
      def define_api_methods(methods)
        methods.each do |key, definition|
          if definition[:collection]
            define_api_method_returning_collection(key, definition)
          else
            define_api_method(key, definition)
          end
        end
      end

      private

      def define_api_method_returning_collection(key, definition)
        define_method key do |*args|
          resp = get_request(key, args[0] || {})
          hashes = resp[definition[:key] || key.to_s]
          Collection.new(resp["total"], resp["start"],
                         resp["session_id"]).tap do |col|
            hashes.each { |hash| col << convert(hash) }
          end
        end
      end

      def define_api_method(key, definition)
        define_method key do |*args|
          resp = get_request(key, args[0] || {})
          convert(resp[definition[:key] || key.to_s])
        end
      end
    end

    def initialize(client)
      @client = client
    end

    private

    def get_request(key, opts)
      query = self.class::METHOD_PREFIX + key.to_s
      get(query, options(opts))["response"]
    end

    def convert(hash)
      hash = Nestling::Hash.new(hash)

      hash.each do |key, value|
        if value.kind_of?(String) &&
          value.match(/\d{4}(-\d\d){2}T\d{2}(:\d\d){2}/)
          hash[key] = DateTime.parse(value)
        elsif value.kind_of?(::Hash)
          hash[key] = convert(value)
        end
      end
    end

    def options(opts)
      opts
    end

    def get(*args)
      @client.get(*args)
    end
  end
end

{'fraction_non_alphanumeric': 0.12294807370184255, 'fraction_numerical': 0.0036850921273031824, 'mean_word_length': 1.916015625, 'pattern_counts': {'":': 0, '<': 9, '<?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': '6303214', 'n_tokens_mistral': 958, 'n_tokens_neox': 922, 'n_words': 203}