Class: SampleManifestExcel::Upload::Data

Inherits:
Object
  • Object
show all
Includes:
ActiveModel::Model, Enumerable, Converters
Defined in:
app/sample_manifest_excel/sample_manifest_excel/upload/data.rb

Overview

An object to store the data for a particular manifest upload. The data is split into a header row (column names) and the actual data.

Constant Summary collapse

SANGER_SAMPLE_ID_COLUMN_LABEL =
'SANGER SAMPLE ID'

Constants included from Converters

Converters::BLANK_CHARS, Converters::BLANK_CHARS_REGEXP

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Converters

#strip_all_blanks

Constructor Details

#initialize(file) ⇒ Data

The file is opened as a Roo spreadsheet. If it is valid it is split by the start row. Start row of column headers and data put into separate rows.


26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'app/sample_manifest_excel/sample_manifest_excel/upload/data.rb', line 26

def initialize(file)
  @file = file
  @file_errors = nil
  @sheet = read_sheet
  @start_row = find_start_row
  return if @start_row.nil?

  @header_row = sheet&.row(@start_row)
  @data = sheet&.drop(@start_row)
  @description_info = extract_description_info(sheet, @start_row)
ensure
  @header_row ||= []
  @data ||= []
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data


13
14
15
# File 'app/sample_manifest_excel/sample_manifest_excel/upload/data.rb', line 13

def data
  @data
end

#description_infoObject (readonly)

Returns the value of attribute description_info


13
14
15
# File 'app/sample_manifest_excel/sample_manifest_excel/upload/data.rb', line 13

def description_info
  @description_info
end

#fileObject (readonly)

Returns the value of attribute file


13
14
15
# File 'app/sample_manifest_excel/sample_manifest_excel/upload/data.rb', line 13

def file
  @file
end

#header_rowObject (readonly)

Returns the value of attribute header_row


13
14
15
# File 'app/sample_manifest_excel/sample_manifest_excel/upload/data.rb', line 13

def header_row
  @header_row
end

#sheetObject (readonly)

Returns the value of attribute sheet


13
14
15
# File 'app/sample_manifest_excel/sample_manifest_excel/upload/data.rb', line 13

def sheet
  @sheet
end

#start_rowObject (readonly)

Returns the value of attribute start_row


13
14
15
# File 'app/sample_manifest_excel/sample_manifest_excel/upload/data.rb', line 13

def start_row
  @start_row
end

Instance Method Details

#cell(row, column) ⇒ Object

Find a cell of data based on the column and row


53
54
55
56
# File 'app/sample_manifest_excel/sample_manifest_excel/upload/data.rb', line 53

def cell(row, column)
  val = data.try(:fetch, row - 1).try(:fetch, column - 1)
  strip_all_blanks(val)
end

#column(col_num) ⇒ Object

Return a column of data for a particular column number


60
61
62
63
64
65
# File 'app/sample_manifest_excel/sample_manifest_excel/upload/data.rb', line 60

def column(col_num)
  data.map do |row|
    val = row[col_num - 1]
    strip_all_blanks(val)
  end
end

#each(&block) ⇒ Object


41
42
43
# File 'app/sample_manifest_excel/sample_manifest_excel/upload/data.rb', line 41

def each(&block)
  data.each(&block)
end

#extract_description_info(sheet, start_row) ⇒ Object


99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'app/sample_manifest_excel/sample_manifest_excel/upload/data.rb', line 99

def extract_description_info(sheet, start_row)
  # look through each row starting from from under the heading (row 2), to above the start row
  # build a hash of the value in the first column => value in second column
  # this was built to extract the tube rack barcodes, and assumes the label is in the first column and the value in the second
  return nil if sheet.nil? || start_row.nil?

  output = {}
  (2..start_row - 1).each do |row_num|
    row = sheet.row(row_num)
    info_label = row[0]
    info_value = row[1]
    output[info_label] = info_value unless info_label.nil?
  end
  output
end

#file_errors_emptyObject


79
80
81
# File 'app/sample_manifest_excel/sample_manifest_excel/upload/data.rb', line 79

def file_errors_empty
  errors.add(:file, @file_errors) if @file_errors.present?
end

#file_extensionObject


45
46
47
48
49
# File 'app/sample_manifest_excel/sample_manifest_excel/upload/data.rb', line 45

def file_extension
  return nil if file.nil?

  File.extname(file.path)
end

#find_start_rowObject


87
88
89
90
91
92
93
94
95
96
97
# File 'app/sample_manifest_excel/sample_manifest_excel/upload/data.rb', line 87

def find_start_row
  return nil if sheet.nil?

  (0..sheet.last_row).each do |row_num|
    sheet.row(row_num).each do |cell_value|
      return row_num if cell_value == SANGER_SAMPLE_ID_COLUMN_LABEL
    end
  end

  nil
end

#inspectObject


83
84
85
# File 'app/sample_manifest_excel/sample_manifest_excel/upload/data.rb', line 83

def inspect
  "<#{self.class}: @header_row=#{header_row}, @data=#{data}, @start_row=#{@start_row}, @file=#{file}>"
end

#read_sheetObject


67
68
69
70
71
72
73
74
75
76
77
# File 'app/sample_manifest_excel/sample_manifest_excel/upload/data.rb', line 67

def read_sheet
  return nil if file.nil?

  Roo::Spreadsheet.open(file).sheet(0)
# In production we see a variety of errors here, all of which indicate problems with the manifest
rescue StandardError => e
  # We store the errors in an instance variable, as otherwise they get lost on any subsequent
  # calls to #valid?
  @file_errors = "could not be read: #{e.message}"
  nil
end