lib/cequel/record/lazy_record_collection.rb
# -*- encoding : utf-8 -*-
module Cequel
module Record
#
# Encapsulates a collection of unloaded {Record} instances. In the case
# where a record set is scoped to fully specify the keys of multiple
# records, those records will be returned unloaded in a
# LazyRecordCollection. When an attribute is read from any of the records
# in a LazyRecordCollection, it will eagerly load all of the records' rows
# from the database.
#
# @since 1.0.0
#
class LazyRecordCollection < DelegateClass(Array)
extend Util::Forwardable
include BulkWrites
#
# @!method table
# (see RecordSet#table)
# @!method connection
# (see RecordSet#connection)
def_delegators :record_set, :table, :connection
#
# @param record_set [RecordSet] record set representing the records in
# this collection
# @api private
#
def initialize(record_set)
fail ArgumentError if record_set.nil?
@record_set = record_set
exploded_key_attributes = [{}].tap do |all_key_attributes|
key_columns.zip(scoped_key_values) do |column, values|
all_key_attributes.replace([values].flatten.compact.flat_map do |value|
all_key_attributes.map do |key_attributes|
key_attributes.merge(column.name => value)
end
end)
end
end
unloaded_records = exploded_key_attributes.map do |key_attributes|
record_set.target_class.new_empty(key_attributes, self)
end
super(unloaded_records)
end
#
# Hydrate all the records in this collection from a database query
#
# @return [LazyRecordCollection] self
def load!
records_by_identity = index_by { |record| record.key_values }
record_set.find_each_row do |row|
identity = row.values_at(*record_set.key_column_names)
records_by_identity[identity].hydrate(row)
end
loaded_count = count { |record| record.loaded? }
if loaded_count < count
fail Cequel::Record::RecordNotFound,
"Expected #{count} results; got #{loaded_count}"
end
self
end
# @private
def assert_fully_specified!
self
end
private
attr_reader :record_set
def_delegators :record_set, :key_columns, :scoped_key_values
private :key_columns, :scoped_key_values
def key_attributes_for_each_row
map { |record| record.key_attributes }
end
end
end
end