class ImportCsv < ApplicationRecord require "csv" mount_uploader :file, FileUploader has_many :import_csv_headers, :dependent => :destroy has_many :import_csv_elements acts_as_tree validates :file, :presence => true validates :table_name, :presence => true has_many :import_csv_champs, :dependent => :destroy accepts_nested_attributes_for :import_csv_champs, :allow_destroy => true acts_as_sorting :fields => { :id => {:name => "Id", :reorder => true}, :created_at => {:name => "Date", :reorder => true}, :name => {:name => "Nom", :reorder => true}, :file => {:name => "Fichier", :reorder => true}, :table_name => {:name => "Table", :reorder => true}, :nbr_headers => {:name => "Nbr champs", :reorder => true}, :nbr_elements => {:name => "Nbr elements", :reorder => true}, :actions => {:name => "Actions", :reorder => false} } after_create do if file_is_csv? csv_text = File.read(self.file.path, :encoding => 'UTF-8') csv = CSV.parse(csv_text, :headers => true, :col_sep => ";") headers = csv.headers else xlsx = Roo::Spreadsheet.open(self.file.path, extension: :xlsx) # open spreadsheet headers = xlsx.row(1) end headers.each do |header| self.import_csv_headers << ImportCsvHeader.new(:name => header) end self.table_name.classify.constantize.import_csv_fields.each do |h| if self.parent and c = self.parent.import_csv_champs.where(:champ => h.to_s).first self.import_csv_champs.new(:champ => h.to_s, :header => c.header) else self.import_csv_champs.new(:champ => h.to_s) end end self.save end def file_is_csv? File.read(self.file.path, :encoding => 'utf-8').valid_encoding? end def charge self.import_csv_elements.each do |e| e.element.destroy if e.element e.destroy end r = [] if file_is_csv? csv_text = File.read(self.file.path, :encoding => 'UTF-8') csv = CSV.parse(csv_text, :headers => true, :col_sep => ";") csv.each do |row| line = {} self.import_csv_champs.each do |import_csv_champ| if import_csv_champ.header? eval "line['#{import_csv_champ.champ}'] = row[\"#{import_csv_champ.header}\"]" elsif import_csv_champ.value? eval "line['#{import_csv_champ.champ}'] = \"#{import_csv_champ.value}\"" end end r << line end return r else xlsx = Roo::Spreadsheet.open(self.file.path, extension: :xlsx) # open spreadsheet headers = xlsx.row(1) # get header row xlsx.each_with_index do |row, idx| line = {} next if idx == 0 # skip header # create hash from headers and cells data = Hash[[headers, row].transpose] self.import_csv_champs.each do |import_csv_champ| # raise if import_csv_champ.header? eval "line['#{import_csv_champ.champ}'] = data[\"#{import_csv_champ.header}\"]" elsif import_csv_champ.value? eval "line['#{import_csv_champ.champ}'] = \"#{import_csv_champ.value}\"" end end r << line end return r end end def load self.table_name.classify.constantize.import_csv(self.charge, self) end end