Class: Receptacle

Inherits:
Asset show all
Includes:
Aliquot::Remover, Commentable, DownstreamAliquotsRemoval::Mixin, StudyReport::AssetDetails, Transfer::State, Uuid::Uuidable
Defined in:
app/models/receptacle.rb

Overview

A receptacle is a container for aliquots, they are associated with Labware, which represents the physical object which moves round the lab. A Labware may have a single Receptacle, such as in the case of a Tube or multiple, in the case of a Plate. Work can be requested on a particular receptacle.

Direct Known Subclasses

Lane, Qc, Well

Defined Under Namespace

Modules: DownstreamAliquotsRemoval Classes: Qc

Constant Summary collapse

QC_STATE_ALIASES =
{ 'passed' => 'pass', 'failed' => 'fail' }.freeze

Constants included from Transfer::State

Transfer::State::ALL_STATES

Instance Method Summary collapse

Methods included from DownstreamAliquotsRemoval::Mixin

#allow_to_remove_downstream_aliquots?

Methods included from StudyReport::AssetDetails

#qc_report

Methods included from Aliquot::Remover

#on_downstream_aliquots, #process_aliquots, #remove_downstream_aliquots, #remove_matching_aliquots

Methods included from Transfer::State

#default_state, #state, #state_from, state_helper

Methods included from Commentable

#after_comment_addition

Methods included from Uuid::Uuidable

included, #unsaved_uuid!, #uuid

Methods inherited from Asset

#ancestor_of_purpose, #asset_type_for_request_types, #barcode_number, #compatible_purposes, #contained_samples, #generate_barcode, #get_qc_result_value_for, #has_stock_asset?, #label, #label=, #original_stock_plates, #prefix, #printable?, #printable_target, #register_stock!, #request_types, #type

Methods included from EventfulRecord

#has_many_events, #has_many_lab_events, #has_one_event_with_family

Methods included from Event::PlateEvents

#event_date, #fluidigm_stamp_date, #gel_qc_date, #pico_date, #qc_started_date, #sequenom_stamp_date

Methods inherited from ApplicationRecord

alias_association, convert_labware_to_receptacle_for, find_by_id_or_name, find_by_id_or_name!

Methods included from Squishify

extended

Instance Method Details

#absolute_position_nameObject

Returns the name of the position (eg. A1) of the receptacle within the context of any tube-rack it may be contained within



328
329
330
# File 'app/models/receptacle.rb', line 328

def absolute_position_name
  racked_tube&.coordinate
end

#any_barcode_matching?(other_barcode) ⇒ Boolean

Returns:

  • (Boolean)


66
67
68
# File 'app/models/receptacle.rb', line 66

def any_barcode_matching?(other_barcode)
  barcodes.any? { |barcode| barcode =~ other_barcode }
end

#api_asset_typeObject

Compatibility for v1 API maintains legacy ‘type’ for assets



313
314
315
# File 'app/models/receptacle.rb', line 313

def api_asset_type
  legacy_asset_type.tableize
end

#assign_tag2(tag) ⇒ Object



239
240
241
242
243
244
# File 'app/models/receptacle.rb', line 239

def assign_tag2(tag)
  aliquots.each do |aliquot|
    aliquot.tag2 = tag
    aliquot.save!
  end
end

#attach_tag(tag, tag2 = nil) ⇒ Object Also known as: attach_tags

Raises:

  • (StandardError)


271
272
273
274
275
276
277
# File 'app/models/receptacle.rb', line 271

def attach_tag(tag, tag2 = nil)
  tags = { tag:, tag2: }.compact
  return if tags.empty?
  raise StandardError, 'Cannot tag an empty asset' if aliquots.empty?

  aliquots.each { |a| a.update!(tags) }
end

#been_through_qc?Boolean

Returns:

  • (Boolean)


228
229
230
# File 'app/models/receptacle.rb', line 228

def been_through_qc?
  qc_state.present?
end

#compatible_qc_stateObject



218
219
220
# File 'app/models/receptacle.rb', line 218

def compatible_qc_state
  QC_STATE_ALIASES.fetch(qc_state, qc_state) || ''
end

#created_with_request_optionsObject



246
247
248
# File 'app/models/receptacle.rb', line 246

def created_with_request_options
  aliquots.first&.created_with_request_options || {}
end

#detailsObject



308
309
310
# File 'app/models/receptacle.rb', line 308

def details
  labware.try(:details).presence || 'Not on labware'
end

#friendly_nameObject



322
323
324
# File 'app/models/receptacle.rb', line 322

def friendly_name
  labware&.friendly_name || id
end

#labware_comment_countObject



193
194
195
# File 'app/models/receptacle.rb', line 193

def labware_comment_count
  labware&.comments&.size || 0
end

#latest_stock_metrics(_product, *_args) ⇒ Object

We only support wells for the time being



285
286
287
# File 'app/models/receptacle.rb', line 285

def latest_stock_metrics(_product, *_args)
  []
end

#legacy_asset_typeObject

Compatibility for v1 API maintains legacy ‘type’ for assets



318
319
320
# File 'app/models/receptacle.rb', line 318

def legacy_asset_type
  labware.sti_type
end

#library_informationObject



236
237
# File 'app/models/receptacle.rb', line 236

def library_information
end

#library_nameObject



304
305
306
# File 'app/models/receptacle.rb', line 304

def library_name
  labware.name
end

#library_typesObject

Library types are still just a string on aliquot.



251
252
253
# File 'app/models/receptacle.rb', line 251

def library_types
  aliquots.pluck(:library_type).uniq
end

#most_recent_requests_as_target_group_by_same_sourceArray<Request>

Groups the requests as target by the same source and returns the most recent request for each source

Returns:

  • (Array<Request>)

    List of requests as target that pass the condition for the current receptacle



340
341
342
343
344
345
346
# File 'app/models/receptacle.rb', line 340

def most_recent_requests_as_target_group_by_same_source
  # Sorts all requests by id, and then index_by will create an object
  # that will store for every asset_id only the last request (request with higher id),
  # ignoring any other request for the same asset_id.
  # From this object we return the list of values, which is an already flattened list
  requests_as_target.order(id: :asc).index_by(&:asset_id).values
end

#nameObject



292
293
294
295
296
# File 'app/models/receptacle.rb', line 292

def name
  labware_name = labware.present? ? labware.try(:name) : '(not on a labware)'
  labware_name ||= labware.display_name # In the event the labware is barcode-less (ie strip tubes) use its name
  labware_name
end

#outer_request(submission_id) ⇒ Object



262
263
264
# File 'app/models/receptacle.rb', line 262

def outer_request(submission_id)
  transfer_requests_as_target.find_by(submission_id:).try(:outer_request)
end

#primary_aliquot_if_uniqueObject



232
233
234
# File 'app/models/receptacle.rb', line 232

def primary_aliquot_if_unique
  primary_aliquot if aliquots.count == 1
end

All studies related to this asset



267
268
269
# File 'app/models/receptacle.rb', line 267

def related_studies
  (ordered_studies + studies).compact.uniq
end

#roleObject



332
333
334
# File 'app/models/receptacle.rb', line 332

def role
  (requests_as_source.first || aliquot_requests.first).role
end

#set_as_library(force: false) ⇒ Object



255
256
257
258
259
260
# File 'app/models/receptacle.rb', line 255

def set_as_library(force: false)
  aliquots.each do |aliquot|
    aliquot.set_library(force:)
    aliquot.save!
  end
end

#set_qc_state(state) ⇒ Object



222
223
224
225
226
# File 'app/models/receptacle.rb', line 222

def set_qc_state(state)
  self.qc_state = QC_STATE_ALIASES.key(state) || state
  save
  set_external_release(qc_state)
end

#tag_rangeString?

Returns the map_id of the first and last tag in an asset eg 1-96. Caution: Used on barcode labels. Avoid using elsewhere as makes assumptions about tag behaviour which may change shortly.

Returns:

  • (String, nil)

    Returns nil is no tags, the map_id is a single tag, or the first and last map id separated by a hyphen if multiple tags.



206
207
208
209
210
211
212
213
214
215
216
# File 'app/models/receptacle.rb', line 206

def tag_range
  map_ids = tags.order(:map_id).pluck(:map_id)
  case map_ids.length
  when 0
    nil
  when 1
    map_ids.first
  else
    "#{map_ids.first}-#{map_ids.last}"
  end
end

#total_comment_countObject



189
190
191
# File 'app/models/receptacle.rb', line 189

def total_comment_count
  comments.size + labware_comment_count
end

#update_aliquot_quality(suboptimal_quality) ⇒ Object



179
180
181
182
# File 'app/models/receptacle.rb', line 179

def update_aliquot_quality(suboptimal_quality)
  aliquots.each { |a| a.update_quality(suboptimal_quality) }
  true
end

#update_from_qc(qc_result) ⇒ Object



298
299
300
# File 'app/models/receptacle.rb', line 298

def update_from_qc(qc_result)
  Tube::AttributeUpdater.update(self, qc_result)
end