Ingredient CSV import input validation
This commit is contained in:
parent
b69bdd6049
commit
3a09bf6fce
@ -1,4 +1,6 @@
|
||||
class IngredientsController < ApplicationController
|
||||
require 'csv'
|
||||
|
||||
before_action :find_project_by_project_id, only: [:index, :create, :import]
|
||||
before_action :find_ingredient, only: [:destroy]
|
||||
before_action :authorize
|
||||
@ -30,6 +32,78 @@ class IngredientsController < ApplicationController
|
||||
end
|
||||
|
||||
def import
|
||||
warnings = []
|
||||
|
||||
if params.has_key?(:file)
|
||||
quantities = @project.quantities.map { |q| [q.name, q] }.to_h
|
||||
units = @project.units.map { |u| [u.shortname, u] }.to_h
|
||||
ingredients = []
|
||||
column_units = {}
|
||||
|
||||
CSV.foreach(params[:file].path, headers: true).with_index(2) do |row, line|
|
||||
r = row.to_h
|
||||
i = {
|
||||
name: r.delete('Name'),
|
||||
group: r.delete('Group') || :other,
|
||||
nutrients_attributes: []
|
||||
}
|
||||
r.each do |col, val|
|
||||
if col.blank?
|
||||
warnings << "Line 1: column header missing" if line == 2
|
||||
next
|
||||
end
|
||||
quantity, quantity_unit_sn, * = col.rstrip.partition(/\[.*\]$/)
|
||||
quantity.strip!
|
||||
if line == 2
|
||||
unless quantities[quantity]
|
||||
warnings << "Line 1: unknown quantity name #{quantity}"
|
||||
end
|
||||
if quantity_unit_sn.present?
|
||||
column_units[quantity] = units[quantity_unit_sn[1..-2]]
|
||||
warnings << "Line 1: unknown unit #{quantity_unit_sn}" \
|
||||
" in column #{col}" unless column_units[quantity]
|
||||
end
|
||||
end
|
||||
next if quantities[quantity].blank? || val.blank?
|
||||
|
||||
amount, amount_unit_sn, * = val.rstrip.partition(/\[.*\]$/)
|
||||
unit = nil
|
||||
if amount_unit_sn.present?
|
||||
unit = units[amount_unit_sn[1..-2]]
|
||||
warnings << "Line #{line}: unknown unit name #{amount_unit_sn}" \
|
||||
" in column #{col}" unless unit
|
||||
else
|
||||
unit = column_units[quantity]
|
||||
# Suppress row warning if column unit error has been reported eariler
|
||||
unless unit || column_units.has_key?(quantity)
|
||||
warnings << "Line #{line}: unknown unit for column #{col}"
|
||||
end
|
||||
end
|
||||
|
||||
if quantity == 'Reference'
|
||||
i.update({
|
||||
ref_amount: amount.to_d,
|
||||
ref_unit: unit
|
||||
})
|
||||
else
|
||||
i[:nutrients_attributes] << {
|
||||
quantity: quantities[quantity],
|
||||
amount: amount.to_d,
|
||||
unit: unit
|
||||
}
|
||||
end
|
||||
end
|
||||
ingredients << i
|
||||
end
|
||||
else
|
||||
warnings << 'No file selected'
|
||||
end
|
||||
|
||||
if warnings.present?
|
||||
warnings.unshift("Problems encountered during import - fix and try again:")
|
||||
flash[:warning] = warnings.join("<br>").truncate(1024, omission: '...(and other)')
|
||||
end
|
||||
redirect_to project_ingredients_url(@project)
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -40,8 +40,13 @@ en:
|
||||
heading_new_ingredient: 'New ingredient'
|
||||
label_import_select_csv_file: 'Select CSV file'
|
||||
import_hints: 'CSV file has to include header with column names. Recognized column
|
||||
names are: (1) ingredient attributes (name, ref_amount, ref_unit, group),
|
||||
(2) quantities names with units short names in square brackets (e.g. proteins [g])'
|
||||
names are:
|
||||
(1) ingredient attributes, case sensitive:
|
||||
"Name" - required, "Reference" - defaults to 100[g], "Group" - defaults to "other",
|
||||
(2) quantities'' names with unit short name in square brackets.
|
||||
Sample header: "Name,Reference,Group,Proteins[g],Fats[g],Carbohydrates[g]".
|
||||
Sample data row: "Brussels,100[g],other,3.4,300[mg],9".
|
||||
Unit given in data row has precedence over that specified in header.'
|
||||
form:
|
||||
button_add_nutrient: 'Add nutrient'
|
||||
button_delete_nutrient: 'Delete'
|
||||
|
Reference in New Issue
Block a user