Skip to content

Commit

Permalink
basics working
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffreyThiessen committed Jan 14, 2025
1 parent 1308394 commit 6bb7ad9
Showing 1 changed file with 163 additions and 0 deletions.
163 changes: 163 additions & 0 deletions app/services/samples/file_import_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# frozen_string_literal: true

require 'roo'

module Samples
# Service used to batch create samples via a file
class FileImportService < BaseService
SampleFileImportError = Class.new(StandardError)

# def initialize(namespace, user = nil, params = {})
def initialize(project, user = nil, params = {})
super(user, params)
@project = project
# @namespace = namespace
@file = params[:file]
@sample_name_column = params[:sample_name_column]
@sample_description_column = params[:sample_description_column] # TODO: do somthing with this
@spreadsheet = nil
@headers = nil
end

def execute
authorize! @project.namespace, to: :update_sample_metadata?

validate_sample_name_column

validate_file

perform_file_import
rescue Samples::FileImportService::SampleFileImportError => e
@namespace.errors.add(:base, e.message)
{}
end

private

def validate_sample_name_column
return unless @sample_name_column.nil?

raise SampleFileImportError,
I18n.t('services.samples.metadata.import_file.empty_sample_id_column')
end

def validate_file_extension
file_extension = File.extname(@file).downcase

return file_extension if %w[.csv .tsv .xls .xlsx].include?(file_extension)

raise SampleFileImportError,
I18n.t('services.samples.metadata.import_file.invalid_file_extension')
end

def validate_file_headers
duplicate_headers = @headers.find_all { |header| @headers.count(header) > 1 }.uniq
unless duplicate_headers.empty?
raise SampleFileImportError,
I18n.t('services.samples.metadata.import_file.duplicate_column_names')
end

unless @headers.include?(@sample_name_column)

Check warning on line 60 in app/services/samples/file_import_service.rb

View workflow job for this annotation

GitHub Actions / runner / rubocop

[rubocop] reported by reviewdog 🐶 Use a guard clause (`return if @headers.include?(@sample_name_column)`) instead of wrapping the code inside a conditional expression. Raw Output: app/services/samples/file_import_service.rb:60:7: C: Style/GuardClause: Use a guard clause (`return if @headers.include?(@sample_name_column)`) instead of wrapping the code inside a conditional expression.
raise SampleFileImportError,
I18n.t('services.samples.metadata.import_file.missing_sample_id_column')
end

# TODO: check if we have a project puid

# return if @headers.count { |header| header != @sample_name_column }.positive?

# raise SampleFileImportError,
# I18n.t('services.samples.metadata.import_file.missing_metadata_column')
end

def validate_file_rows
# Should have at least 2 rows
first_row = @spreadsheet.row(2)
return unless first_row.compact.empty?

raise SampleFileImportError,
I18n.t('services.samples.metadata.import_file.missing_metadata_row')
end

def validate_file
if @file.nil?
raise SampleFileImportError,
I18n.t('services.samples.metadata.import_file.empty_file')
end

extension = validate_file_extension

@spreadsheet = if extension.eql? '.tsv'
Roo::CSV.new(@file, csv_options: { col_sep: "\t" })
else
Roo::Spreadsheet.open(@file)
end

@headers = @spreadsheet.row(1).compact

validate_file_headers

validate_file_rows
end

def perform_file_import
response = {}
parse_settings = @headers.zip(@headers).to_h

@spreadsheet.each_with_index(parse_settings) do |data, index|
next unless index.positive?

# TODO: next when all data is nil (empty line)

sample_name = data[@sample_name_column]

# TODO: do work here

response[sample_name] = process_sample_row(sample_name, nil) # TODO
rescue ActiveRecord::RecordNotFound
@project.errors.add(:sample, error_message(sample_name))
end
response
end

def error_message(sample_id) # TODO: remove

Check warning on line 123 in app/services/samples/file_import_service.rb

View workflow job for this annotation

GitHub Actions / runner / rubocop

[rubocop] reported by reviewdog 🐶 Do not place comments on the same line as the `def` keyword. Raw Output: app/services/samples/file_import_service.rb:123:34: C: Style/CommentedKeyword: Do not place comments on the same line as the `def` keyword.
if @namespace.type == 'Group'
I18n.t('services.samples.metadata.import_file.sample_not_found_within_group', sample_puid: sample_id)
else
I18n.t('services.samples.metadata.import_file.sample_not_found_within_project', sample_puid: sample_id)
end
end

def process_sample_row(name, description)
sample_params = { name:, description: }
sample = Samples::CreateService.new(current_user, @project, sample_params).execute

if sample.persisted?
sample
else
sample.errors.map do |error| # TODO: rework this error
{
path: ['sample', error.attribute.to_s.camelize(:lower)],
message: error.message
}
end
end
end

# def find_sample(sample_id)
# if @namespace.type == 'Group'
# authorized_scope(Sample, type: :relation, as: :namespace_samples,
# scope_options: { namespace: @namespace,
# minimum_access_level: Member::AccessLevel::MAINTAINER })
# .find_by!(puid: sample_id)
# else
# project = @namespace.project
# if Irida::PersistentUniqueId.valid_puid?(sample_id, Sample)
# Sample.find_by!(puid: sample_id, project_id: project.id)
# else
# Sample.find_by!(name: sample_id, project_id: project.id)
# end
# end
# end
end
end

0 comments on commit 6bb7ad9

Please sign in to comment.