sanger/limber

View on GitHub
app/models/presenters/tubes_with_sources.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
94%
# frozen_string_literal: true

# Groups tubes with the wells that get transferred into them
# Used by the plate presenter to ensure consistent colour-coding
# and annotation with source well information
class Presenters::TubesWithSources
  # Wrapper for the tube collection array
  class Collection
    attr_reader :array

    def initialize(array)
      @array = array
    end

    def tubes?
      @array.present?
    end

    def tube_labels
      # Optimization: To avoid needing to load in the tube aliquots, we use the transfers into the
      # tube to work out the pool size. This information is already available. Two values are different
      # for ISC though. TODO: MUST RE-JIG

      # Tubes might have different labels in purpose config. Load the right labels to avoid different behaviour.
      @array.map do |tube|
        config = Settings.purposes.fetch(tube.purpose&.uuid, {})
        label_class = config.fetch(:label_class, 'Labels::TubeLabel')
        label_class.constantize.new(tube, pool_size: tube.pool_size)
      end
    end

    delegate_missing_to :array
  end

  def self.build(wells:, pools:)
    Collection.new(
      wells
        .each_with_object({}) do |well, store|
          well.downstream_tubes.each do |tube|
            store[tube] ||= new(tube, pools)
            store[tube] << well
          end
        end
        .values
    )
  end

  attr_reader :tube

  def initialize(tube, pools)
    @tube = tube
    @pools = pools
    @sources = []
  end

  def <<(well)
    @sources << well
  end

  # Returns the pool id based on the shared submission between the wells
  def pool_id
    @sources.map(&:submission_ids).reduce { |common_ids, current_ids| common_ids & current_ids }.first
  end

  def pool_index
    @pools.pool_index(pool_id)
  end

  def source_locations
    @sources.map(&:location)
  end

  def pool_size
    @sources.sum { |well| well.aliquots.count }
  end

  delegate_missing_to :tube
end