Fetcher/mongo-fixture

View on GitHub
lib/mongo-fixture/inserter.rb

Summary

Maintainability
A
1 hr
Test Coverage
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