<commit_before>module CollectionSpace

  # http://www.garrettqmartin.com/2015/02/03/finding-deeply-nested-hash-keys/
  module DeepFind
    def deep_find(obj, key, nested_key = nil)
      return obj[key] if obj.respond_to?(:key?) && obj.key?(key)
      if obj.is_a? Enumerable
        found = nil
        obj.find { |*a| found = deep_find(a.last, key) }
        if nested_key
          deep_find(found, nested_key)
        else
          found
        end
      end
    end
  end

  module Helpers

    # get ALL records at path by paging through record set
    # can pass block to act on each page of results
    def all(path, options = {}, &block)
      all = []
      result = request('GET', path, options)
      raise RequestError.new result.status if result.status_code != 200 or result.parsed['abstract_common_list'].nil?

      total = result.parsed['abstract_common_list']['totalItems'].to_i
      items = result.parsed['abstract_common_list']['itemsInPage'].to_i
      return all if total == 0

      pages = (total / config.page_size) + 1
      (0 .. pages - 1).each do |i|
        options[:query][:pgNum] = i
        result     = request('GET', path, options)
        raise RequestError.new result.status if result.status_code != 200
        list_items = result.parsed['abstract_common_list']['list_item']
        list_items = [ list_items ] if items == 1
        list_items.each { |item| yield item if block_given? }
        all.concat list_items
      end
      all
    end

    def count(path)
      # make sure path is only 1 level deep?
      count  = nil
      result = request('GET', path, { query: { pgSz: 1 } })
      count  = result.parsed['abstract_common_list']['totalItems'].to_i if result.status_code == 200
      count
    end

    # create blob record by external url
    def post_blob_url(url)
      raise ArgumentError.new("Invalid blob URL #{url}") unless URI.parse(url).scheme =~ /^https?/
      request 'POST', "blobs", {
        query: { "blobUri" => url },
      }
    end

    def post_relationship(type_a, csid_a, type_b, csid_b)
      # requires an erb template
      # request 'POST', "relations", { body: payload }
      # flip for reciprocal relationship
      # request 'POST', "relations", { body: payload }
    end

    def search(query, options = {})
      query_string = "#{query.type}:#{query.field} #{query.expression}"
      options = options.merge({ query: { as: query_string } })
      request "GET", query.path, options
    end

    def strip_refname(refname)
      refname.match(/('.*')/)[0].delete("'")
    end

  end

end<commit_msg>Support relations with all helper<commit_after>module CollectionSpace

  # http://www.garrettqmartin.com/2015/02/03/finding-deeply-nested-hash-keys/
  module DeepFind
    def deep_find(obj, key, nested_key = nil)
      return obj[key] if obj.respond_to?(:key?) && obj.key?(key)
      if obj.is_a? Enumerable
        found = nil
        obj.find { |*a| found = deep_find(a.last, key) }
        if nested_key
          deep_find(found, nested_key)
        else
          found
        end
      end
    end
  end

  module Helpers

    # get ALL records at path by paging through record set
    # can pass block to act on each page of results
    def all(path, options = {}, &block)
      all = []
      list_type, list_item = get_list_types(path)

      result = request('GET', path, options)
      raise RequestError.new result.status if result.status_code != 200 or result.parsed[list_type].nil?

      total = result.parsed[list_type]['totalItems'].to_i
      items = result.parsed[list_type]['itemsInPage'].to_i
      return all if total == 0

      pages = (total / config.page_size) + 1
      (0 .. pages - 1).each do |i|
        options[:query][:pgNum] = i
        result     = request('GET', path, options)
        raise RequestError.new result.status if result.status_code != 200
        list_items = result.parsed[list_type][list_item]
        list_items = [ list_items ] if items == 1
        list_items.each { |item| yield item if block_given? }
        all.concat list_items
      end
      all
    end

    def count(path)
      # make sure path is only 1 level deep?
      count  = nil
      result = request('GET', path, { query: { pgSz: 1 } })
      count  = result.parsed['abstract_common_list']['totalItems'].to_i if result.status_code == 200
      count
    end

    # create blob record by external url
    def post_blob_url(url)
      raise ArgumentError.new("Invalid blob URL #{url}") unless URI.parse(url).scheme =~ /^https?/
      request 'POST', "blobs", {
        query: { "blobUri" => url },
      }
    end

    def post_relationship(type_a, csid_a, type_b, csid_b)
      # requires an erb template
      # request 'POST', "relations", { body: payload }
      # flip for reciprocal relationship
      # request 'POST', "relations", { body: payload }
    end

    def search(query, options = {})
      query_string = "#{query.type}:#{query.field} #{query.expression}"
      options = options.merge({ query: { as: query_string } })
      request "GET", query.path, options
    end

    def strip_refname(refname)
      refname.match(/('.*')/)[0].delete("'")
    end

    private

    def get_list_types(path)
      list_type, list_item = nil
      if path == 'relations'
        list_type = 'relations_common_list'
        list_item = 'relation_list_item'
      else
        list_type = 'abstract_common_list'
        list_item = 'list_item'
      end
      return list_type, list_item
    end

  end

end
{'fraction_non_alphanumeric': 0.11836142831248866, 'fraction_numerical': 0.00906289650172195, 'mean_word_length': 2.4901960784313726, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '1350847', 'n_tokens_mistral': 1766, 'n_tokens_neox': 1698, 'n_words': 461}