Class: PlateVolume

Inherits:
ApplicationRecord show all
Extended by:
DbFile::Uploader
Defined in:
app/models/plate_volume.rb

Constant Summary collapse

ASSAY_TYPE =
'Volume Check'
ASSAY_VERSION =
'1.0'

Class Method Summary collapse

Instance Method Summary collapse

Methods included from DbFile::Uploader

extended, has_uploaded

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

Class Method Details

.all_plate_volume_file_names(folder) ⇒ Object

Returns an array of plate volume file names in the provided folder. Filters out directories, non-CSV files, and files larger than 500 KB.



90
91
92
93
94
95
96
97
# File 'app/models/plate_volume.rb', line 90

def all_plate_volume_file_names(folder)
  Dir.entries(folder).reject do |f|
    path = File.join(folder, f)
    File.directory?(path) || # is a directory
      File.extname(f).downcase != '.csv' || # not a .csv file
      File.size(path) > 500 * 1024 # > 500 KB
  end
end

.bugfix_filename_duplicate_back_to_normal(filename) ⇒ Object

Given a .csv filename it removes the characters (2) that were appended to indicate the file was a duplicate. This is currently happening to files handled by CarrierWave during the save() action.

An example of this method, suppose file1.csv –> file1(2).csv then the action of this method would revert file1(2).csv into file1.csv



144
145
146
147
148
# File 'app/models/plate_volume.rb', line 144

def bugfix_filename_duplicate_back_to_normal(filename)
  matching_regexp = /\(\d*\)\.CSV/i
  filename.gsub!(matching_regexp, '.csv') if filename.match(matching_regexp)
  filename
end

.find_for_filename(filename) ⇒ Object

rubocop:disable Metrics/MethodLength



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/plate_volume.rb', line 114

def find_for_filename(filename)
  find_by(uploaded_file_name: filename) or
    lambda do |filename, file|
      # TODO: After saving, the uploaded_file_name is renamed internally by CarrierWave to (2).CSV
      # This should be amended in future.
      Rails.logger.info("Creating new PlateVolume record for volume check file '#{filename}'")

      instance = PlateVolume.new(uploaded_file_name: filename, updated_at: file.stat.mtime, uploaded: file)
      instance.save
    ensure
      unless instance.nil?
        ActiveRecord::Base.with_connection do |connection|
          connection.execute(<<~SQL.squish)
            UPDATE plate_volumes
            SET uploaded_file_name='#{bugfix_filename_duplicate_back_to_normal(instance.uploaded_file_name)}'
            WHERE plate_volumes.id=#{instance.id}
          SQL
        end
      end
    end
end

.handle_volume(filename, file) ⇒ Object



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

def handle_volume(filename, file)
  ActiveRecord::Base.transaction { find_for_filename(sanitized_filename(file)).call(filename, file) }
rescue => e
  Rails.logger.warn("Error processing volume check file #{filename}: #{e.message}")
end

.process_all_volume_check_files(folder = configatron.plate_volume_files) ⇒ Object

Processes all plate volume check CSV files in the specified folder. For each valid file, it uploads a copy and updates the plate volumes as a QcResult, skipping files that are directories, not CSV, or larger than 500 KB.



78
79
80
81
82
83
84
85
86
# File 'app/models/plate_volume.rb', line 78

def process_all_volume_check_files(folder = configatron.plate_volume_files)
  Rails.logger.info("Starting processing of volume check files in folder: #{folder}")

  all_plate_volume_file_names(folder).each do |filename|
    File.open(File.join(folder, filename), 'r') { |file| catch(:no_source_plate) { handle_volume(filename, file) } }
  end

  Rails.logger.info('Completed processing of volume check files')
end

.sanitized_filename(file) ⇒ Object



107
108
109
110
111
# File 'app/models/plate_volume.rb', line 107

def sanitized_filename(file)
  # We need to use the Carrierwave sanitized filename for lookup, else files with spaces are repetedly processed
  # Later versions of carrierwave expose this sanitization better, but for now we are forced to create an object
  CarrierWave::SanitizedFile.new(file).filename
end

Instance Method Details

#call(filename, file) ⇒ Object



19
20
21
22
23
24
25
# File 'app/models/plate_volume.rb', line 19

def call(filename, file)
  return unless update_required?(file.stat.mtime)

  db_files.map(&:destroy)
  reload
  update!(uploaded_file_name: filename, updated_at: file.stat.mtime, uploaded: file)
end

#update_required?(modified_timestamp) ⇒ Boolean

Is an update required given the timestamp specified

Returns:

  • (Boolean)


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

def update_required?(modified_timestamp)
  updated_at.to_i < modified_timestamp.to_i
end