lib/restforce/collection.rb



# frozen_string_literal: true

module Restforce
  class Collection
    include Enumerable

    # Given a hash and client, will create an Enumerator that will lazily
    # request Salesforce for the next page of results.
    def initialize(hash, client)
      @client = client
      @raw_page = hash
    end

    # Yield each value on each page.
    def each(&block)
      @raw_page['records'].each { |record| yield Restforce::Mash.build(record, @client) }

      np = next_page
      while np
        np.current_page.each(&block)
        np = np.next_page
      end
    end

    # Return the size of each page in the collection
    def page_size
      @raw_page['records'].size
    end

    # Return the number of items in the Collection without making any additional
    # requests and going through all of the pages of results, one by one. Instead,
    # we can rely on the total count of results which Salesforce returns.
    def size
      @raw_page['totalSize']
    end
    alias length size

    def count(*args)
      # By default, `Enumerable`'s `#count` uses `#each`, which means going through all
      # of the pages of results, one by one. Instead, we can use `#size` which we have
      # already overridden to work in a smarter, more efficient way. This only works for
      # the simple version of `#count` with no arguments. When called with an argument or
      # a block, you need to know what the items in the collection actually are, so we
      # call `super` and end up iterating through each item in the collection.
      return size unless block_given? || !args.empty?

      super
    end

    # Returns true if the size of the Collection is zero.
    def empty?
      size.zero?
    end

    # Return array of the elements on the current page
    def current_page
      first(@raw_page['records'].size)
    end

    # Return the current and all of the following pages.
    def pages
      [self] + (has_next_page? ? next_page.pages : [])
    end

    # Returns true if there is a pointer to the next page.
    def has_next_page?
      !@raw_page['nextRecordsUrl'].nil?
    end

    # Returns the next page as a Restforce::Collection if it's available, nil otherwise.
    def next_page
      @client.get(@raw_page['nextRecordsUrl']).body if has_next_page?
    end
  end
end