Class: Reception::ResourceFactory

Inherits:
Object
  • Object
show all
Extended by:
NestedValidation
Includes:
ActiveModel::Model
Defined in:
app/models/reception/resource_factory.rb

Overview

Acts on behalf of a Reception to construct all associated requests, as well as any necessary samples, plates, wells and tubes. In order to improve performance, the ResourceFactory implements caching of samples and library and data types. This allows up to retrieve all records in a single query upfront, avoiding N+1 query problems. It also ensures we can centralize the registration of new plates and tubes, making it easier to prevent registration of duplicate records.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from NestedValidation

validates_nested

Instance Attribute Details

#receptionObject

Returns the value of attribute reception.



15
16
17
# File 'app/models/reception/resource_factory.rb', line 15

def reception
  @reception
end

Instance Method Details

#compound_sample_tubes_attributes=(compound_sample_tubes_attributes) ⇒ Object

method to handle compound tubes attributes



30
31
32
# File 'app/models/reception/resource_factory.rb', line 30

def compound_sample_tubes_attributes=(compound_sample_tubes_attributes)
  create_compound_tubes(compound_sample_tubes_attributes)
end

#construct_resources!Object



58
59
60
61
# File 'app/models/reception/resource_factory.rb', line 58

def construct_resources!
  requests.each(&:save!) # Note this also saves associated records we generate
  labware_status
end

#containersObject



46
47
48
# File 'app/models/reception/resource_factory.rb', line 46

def containers
  @containers ||= []
end

#create_compound_tubes(compound_tube_attributes) ⇒ Object



100
101
102
103
104
# File 'app/models/reception/resource_factory.rb', line 100

def create_compound_tubes(compound_tube_attributes)
  compound_tube_attributes.each do |tube_attr|
    process_compound_tube(tube_attr)
  end
end

#create_plates(plates_attributes) ⇒ Object

Populates containers and requests from plates_attributes



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'app/models/reception/resource_factory.rb', line 64

def create_plates(plates_attributes)
  plates_attributes.each do |plate_attr|
    # Gets the existing plate or creates a new one
    plate = find_or_create_labware(plate_attr[:barcode], Plate)
    containers << plate
    plate_attr[:wells_attributes].each do |well_attr|
      # Gets the existing well or creates a new one
      well = plate.wells.located_at(well_attr[:position])
      # If a well already exists with records, we want to add an error
      if well.existing_records.present?
        update_labware_status(plate.barcode, 'partial', "#{well.position} already has a sample")
        next
      end

      # Creates a request for the well
      create_request_for_container(well_attr, well)
    end
  end
end

#create_pool(pool_attributes) ⇒ Object

Creates a pool from pool_attributes and uses the imported libraries



107
108
109
110
111
112
113
114
115
116
117
118
# File 'app/models/reception/resource_factory.rb', line 107

def create_pool(pool_attributes)
  return if pool_attributes.blank?

  # Currently only supports Ont
  @pool = Ont::Pool.new(pool_attributes)
  begin
    @pool.libraries = libraries
    update_labware_status(pool_attributes['barcode'], 'success', nil)
  rescue StandardError => e
    update_labware_status(pool_attributes['barcode'], 'failed', e.message)
  end
end

#create_tubes(tubes_attributes) ⇒ Object

Populates containers and requests from tubes_attributes



85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'app/models/reception/resource_factory.rb', line 85

def create_tubes(tubes_attributes)
  tubes_attributes.each do |tube_attr|
    # Gets the existing tube or creates a new one
    tube = find_or_create_labware(tube_attr[:barcode], Tube)
    # If a tube already exists with records, we want to add an error
    if tube.existing_records.present?
      update_labware_status(tube.barcode, 'failed', 'Tube already has a sample')
      next
    end

    # Creates a request for the tube
    create_request_for_container(tube_attr, tube)
  end
end

#data_type_for(attributes) ⇒ Object



130
131
132
# File 'app/models/reception/resource_factory.rb', line 130

def data_type_for(attributes)
  data_type_cache.fetch(attributes[:data_type], nil)
end

#labware_statusObject



54
55
56
# File 'app/models/reception/resource_factory.rb', line 54

def labware_status
  @labware_status ||= {}
end

#librariesObject



42
43
44
# File 'app/models/reception/resource_factory.rb', line 42

def libraries
  @libraries ||= []
end

#library_type_for(request_attributes) ⇒ Object



120
121
122
123
124
125
126
127
128
# File 'app/models/reception/resource_factory.rb', line 120

def library_type_for(request_attributes)
  # Gets a library type from the cache or returns an unknown type
  library_type = request_attributes[:library_type]
  library_type_cache.fetch(
    library_type,
    UnknownLibraryType.new(library_type:,
                           permitted: library_type_cache.keys)
  )
end

#plates_attributes=(plates_attributes) ⇒ Object



21
22
23
# File 'app/models/reception/resource_factory.rb', line 21

def plates_attributes=(plates_attributes)
  create_plates(plates_attributes)
end

#poolObject



38
39
40
# File 'app/models/reception/resource_factory.rb', line 38

def pool
  @pool ||= nil
end

#pool_attributes=(pool_attributes) ⇒ Object



34
35
36
# File 'app/models/reception/resource_factory.rb', line 34

def pool_attributes=(pool_attributes)
  create_pool(pool_attributes)
end

#requestsObject



50
51
52
# File 'app/models/reception/resource_factory.rb', line 50

def requests
  @requests ||= []
end

#sample_for(attributes) ⇒ Object



134
135
136
137
138
139
140
# File 'app/models/reception/resource_factory.rb', line 134

def sample_for(attributes)
  # Used to reduce database queries.
  # It gets a sample from the cache, if it doesn't exist it searches the database
  # or creates a new one
  sample_cache[attributes[:external_id]] ||=
    Sample.find_by(external_id: attributes[:external_id]) || Sample.new(attributes)
end

#tubes_attributes=(tubes_attributes) ⇒ Object



25
26
27
# File 'app/models/reception/resource_factory.rb', line 25

def tubes_attributes=(tubes_attributes)
  create_tubes(tubes_attributes)
end