lib/praxis-mapper/identity_map.rb
def finalize_model!(model, query = nil)
      staged_queries = @staged[model].delete(:_queries) || []
      staged_keys = @staged[model].keys
      non_identities = staged_keys - model.identities

      results = Set.new

      return results if @staged[model].all? { |(_key, values)| values.empty? }

      if query.nil?
        query_class = @connection_manager.repository(model.repository_name)[:query]
        query = query_class.new(self, model)
      end

      # Apply any relevant blocks passed to track in the original queries
      staged_queries.each do |staged_query|
        staged_query.track.each do |(association_name, block)|
          next unless block

          spec = staged_query.model.associations[association_name]

          if spec[:model] == model
            query.instance_eval(&block)
            if (spec[:type] == :many_to_one || spec[:type] == :array_to_many) && query.where
              file, line = block.source_location
              trace = ["#{file}:#{line}"] | caller
              raise RuntimeError, "Error finalizing model #{model.name} for association #{association_name.inspect} -- using a where clause when tracking associations of type #{spec[:type].inspect} is not supported", trace
            end
          end
        end
      end


      # process non-unique staged keys
      #   select identity (any one should do) for those keys and stage blindly
      #   load and add records.

      if non_identities.any?
        to_stage = Hash.new do |hash,identity|
          hash[identity] = Set.new
        end

        non_identities.each do |key|
          values = @staged[model].delete(key)

          rows = query.multi_get(key, values, select: model.identities, raw: true)
          rows.each do |row|
            model.identities.each do |identity|
              if identity.kind_of? Array
                to_stage[identity] << row.values_at(*identity)
              else
                to_stage[identity] << row[identity]
              end
            end
          end
        end

        self.stage(model, to_stage)
      end

      model.identities.each do |identity_name|
        values = self.get_staged(model,identity_name)
        next if values.empty?

        query.where = nil # clear out any where clause from non-identity
        records = query.multi_get(identity_name, values)

        # TODO: refactor this to better-hide queries?
        self.queries[model].add(query)

        results.merge(add_records(records))

        # add nil records for records that were not found by the multi_get
        missing_keys = self.get_staged(model,identity_name)
        missing_keys.each do |missing_key|
          @row_keys[model][identity_name][missing_key] = nil
          get_staged(model, identity_name).delete(missing_key)
        end

      end

      query.freeze

      # TODO: check whether really really did get all the records we should have....
      results.to_a
    end
def finalize_model!(model, query = nil)
      staged_queries = @staged[model].delete(:_queries) || []
      staged_keys = @staged[model].keys
      non_identities = staged_keys - model.identities

      results = Set.new

      return results if @staged[model].all? { |(_key, values)| values.empty? }

      if query.nil?
        query_class = @connection_manager.repository(model.repository_name)[:query]
        query = query_class.new(self, model)
      end

      # Apply any relevant blocks passed to track in the original queries
      staged_queries.each do |staged_query|
        staged_query.track.each do |(association_name, block)|
          next unless block

          spec = staged_query.model.associations[association_name]

          if spec[:model] == model
            query.instance_eval(&block)
            if (spec[:type] == :many_to_one || spec[:type] == :array_to_many) && query.where
              file, line = block.source_location
              trace = ["#{file}:#{line}"] | caller
              raise RuntimeError, "Error finalizing model #{model.name} for association #{association_name.inspect} -- using a where clause when tracking associations of type #{spec[:type].inspect} is not supported", trace
            end
          end
        end
      end


      # process non-unique staged keys
      #   select identity (any one should do) for those keys and stage blindly
      #   load and add records.

      if non_identities.any?
        to_stage = Hash.new do |hash,identity|
          hash[identity] = Set.new
        end

        non_identities.each do |key|
          values = @staged[model].delete(key)

          rows = query.multi_get(key, values, select: model.identities, raw: true)
          rows.each do |row|
            model.identities.each do |identity|
              if identity.kind_of? Array
                to_stage[identity] << row.values_at(*identity)
              else
                to_stage[identity] << row[identity]
              end
            end
          end
        end

        self.stage(model, to_stage)
      end

      model.identities.each do |identity_name|
        values = self.get_staged(model,identity_name)
        next if values.empty?

        query.where = nil # clear out any where clause from non-identity
        records = query.multi_get(identity_name, values)

        # TODO: refactor this to better-hide queries?
        self.queries[model].add(query)

        results.merge(add_records(records))

        # add nil records for records that were not found by the multi_get
        missing_keys = self.get_staged(model,identity_name)
        missing_keys.each do |missing_key|
          @row_keys[model][identity_name][missing_key] = nil
          get_staged(model, identity_name).delete(missing_key)
        end

      end

      query.freeze

      # TODO: check whether really really did get all the records we should have....
      results.to_a
    end
don't doc. never ever use yourself!
 FIXME: make private and fix specs that break?