lib/mongo-fixture/inserter.rb
module Mongo
class Fixture
# Handles the actual insertion into the database.
class Inserter
# Receives a fixture as argument
def initialize fixture
@fixture = fixture
@inserted = []
end
# Simplifies the hash in order to insert it into the database
# Resolves external references and flattens the values that provide alternatives
# @param [Hash] the hash to be processed
def simplify the_record
the_returned_hash = {}
the_record.each do |field, value|
begin
value = resolve_field_hash value if value.is_a? Hash
rescue Mongo::Fixture::ReferencedRecordNotFoundError => e
@fixture.rollback
raise e
end
the_returned_hash[field] = value
end
return the_returned_hash
end
# Returns the correct data for this field resolving the hash
def resolve_field_hash value
raise ArgumentError, "Hash expected" unless value.is_a? Hash
return value[:processed] if value.has_key? :processed
intersection = value.keys & @fixture.data.keys
if intersection.empty?
raise Mongo::Fixture::ReferencedRecordNotFoundError,
"This fixture does not include data for the collections [#{value.keys.join(',')}]"
else
intersection.each do |collection|
insert_data_for collection unless data_was_inserted_in? collection
if value[collection].is_a? Array
ids = []
value[collection].each do |element|
ids.push do_the_resolving collection, element.to_sym
end
return ids
else
return do_the_resolving collection, value[collection].to_sym
end
end
end
end
# options = value.keys & @fixture.data.keys
# # If no alternative matches the name of a collection, look for a :processed value
# if options.empty?
# unless value.has_key? :processed
# raise MissingProcessedValueError.new "The processed value to insert into the db is missing from the field '#{field}', aborting", field
# end
# the_returned_hash[field] = value[:processed]
# else
#
# # Does any of the options hold a record named after the value of the option?
# actual_option = options.each do |option|
# break option if @fixture.data[option].has_key? value[option].to_sym
# end
#
# unless data_was_inserted_in? actual_option
# insert_data_for actual_option
# end
# current_collection = @connection[actual_option]
# current_data = simplify @fixture.data[actual_option][value[actual_option].to_sym]
# the_returned_hash[field] = current_collection.find(current_data).first["_id"]
# end
# Inserts the collection data into the database
def insert_data_for collection
# @data.each do |collection, matrix|
# unless @inserter.data_was_inserted_in? collection
# matrix.each do |element, values|
# begin
# @connection[collection].insert @inserter.simplify values.to_hash
# rescue MissingProcessedValueError => m
# rollback
# raise MissingProcessedValueError, "In record '#{element}' to be inserted into '#{collection}', the processed value of field '#{m.field}' is missing, aborting"
# end
# end
# @inserted << collection
# end
return if data_was_inserted_in? collection
@fixture.data[collection].each do |key, record|
begin
@fixture.connection[collection].insert simplify record
rescue MissingProcessedValueError => m
@fixture.rollback
raise MissingProcessedValueError, "In record '#{key}' to be inserted into '#{collection}', the processed value of field '#{m.field}' is missing, aborting"
end
end
@inserted << collection
end
# Returns true if the collection was already inserted
def data_was_inserted_in? collection
@inserted.include? collection
end
def inserted
@inserted
end
# Returns the fixture
attr_reader :fixture
private
def validate_record_existence collection, record_name
unless @fixture.data[collection].has_key? record_name
raise Mongo::Fixture::ReferencedRecordNotFoundError,
"The collection '#{collection}' doesn't include the record '#{record_name}'"
end
end
def do_the_resolving collection, record_name
validate_record_existence collection, record_name
record_data = simplify @fixture.data[collection][record_name]
return @fixture.connection[collection].find(record_data).first["_id"]
end
end
end
end