lib/aws-record/record/item_collection.rb (56 lines of code) (raw):
# frozen_string_literal: true
module Aws
module Record
class ItemCollection
include Enumerable
def initialize(search_method, search_params, model, client)
@search_method = search_method
@search_params = search_params
@model_filter = @search_params.delete(:model_filter)
@model = model
@client = client
end
# Provides an enumeration of the results of a query or scan operation on
# your table, automatically converted into item classes.
#
# WARNING: This will enumerate over your entire partition in the case of
# query, and over your entire table in the case of scan, save for key and
# filter expressions used. This means that enumerable operations that
# iterate over the full result set could make many network calls, or use a
# lot of memory to build response objects. Use with caution.
#
# @return [Enumerable<Aws::Record>] an enumeration over the results of
# your query or scan request. These results are automatically converted
# into items on your behalf.
def each(&block)
return enum_for(:each) unless block_given?
items.each_page do |page|
@last_evaluated_key = page.last_evaluated_key
items_array = _build_items_from_response(page.items, @model)
items_array.each(&block)
end
end
# Provides the first "page" of responses from your query operation. This
# will only make a single client call, and will provide the items, if any
# exist, from that response. It will not attempt to follow up on
# pagination tokens, so this is not guaranteed to include all items that
# match your search.
#
# @return [Array<Aws::Record>] an array of the record items found in the
# first page of responses from the query or scan call.
def page
search_response = items
@last_evaluated_key = search_response.last_evaluated_key
_build_items_from_response(search_response.items, @model)
end
# Provides the pagination key most recently used by the underlying client.
# This can be useful in the case where you're exposing pagination to an
# outside caller, and want to be able to "resume" your scan in a new call
# without starting over.
#
# @return [Hash] a hash representing an attribute key/value pair, suitable
# for use as the +exclusive_start_key+ in another query or scan
# operation. If there are no more pages in the result, will be nil.
def last_evaluated_key
@last_evaluated_key
end
# Checks if the query/scan result is completely blank.
#
# WARNING: This can and will query your entire partition, or scan your
# entire table, if no results are found. Especially if your table is
# large, use this with extreme caution.
#
# @return [Boolean] true if the query/scan result is empty, false
# otherwise.
def empty?
items.each_page do |page|
return false unless page.items.empty?
end
true
end
private
def _build_items_from_response(items, model)
ret = []
items.each do |item|
model_class = @model_filter ? @model_filter.call(item) : model
next unless model_class
record = model_class.new
data = record.instance_variable_get('@data')
model_class.attributes.attributes.each do |name, attr|
data.set_attribute(name, attr.extract(item))
end
data.clean!
data.new_record = false
ret << record
end
ret
end
def items
@items ||= @client.send(@search_method, @search_params)
end
end
end
end