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.



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

def reception
  @reception
end

Instance Method Details

#compound_sample_tubes_attributes=(compound_sample_tubes_attributes) ⇒ Object

method to handle compound tubes attributes



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

def compound_sample_tubes_attributes=(compound_sample_tubes_attributes)
  create_compound_tubes(compound_sample_tubes_attributes)
end

#construct_resources!Object



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

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

#containersObject



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

def containers
  @containers ||= []
end

#create_compound_tubes(compound_tube_attributes) ⇒ Object



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

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



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

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



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

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



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

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



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

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

#labware_statusObject



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

def labware_status
  @labware_status ||= {}
end

#librariesObject



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

def libraries
  @libraries ||= []
end

#library_type_for(request_attributes) ⇒ Object



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

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



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

def plates_attributes=(plates_attributes)
  create_plates(plates_attributes)
end

#poolObject



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

def pool
  @pool ||= nil
end

#pool_attributes=(pool_attributes) ⇒ Object



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

def pool_attributes=(pool_attributes)
  create_pool(pool_attributes)
end

#requestsObject



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

def requests
  @requests ||= []
end

#sample_for(attributes) ⇒ Object



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

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



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

def tubes_attributes=(tubes_attributes)
  create_tubes(tubes_attributes)
end