module AdHocTemplate::RecordReader::CSVReader
Constants
- COL_SEP
Public Class Methods
dump(config_data, col_sep=COL_SEP[:csv])
click to toggle source
# File lib/ad_hoc_template/record_reader.rb, line 59 def self.dump(config_data, col_sep=COL_SEP[:csv]) data = RecordReader.parse_if_necessary(config_data) raise NotSupportedError unless csv_compatible_format?(data) kv_pairs = find_sub_records(data) records = kv_pairs ? hashes_to_arrays(kv_pairs) : data.to_a.transpose array_to_csv(records, col_sep) end
read_record(csv_data, config={ csv: nil })
click to toggle source
# File lib/ad_hoc_template/record_reader.rb, line 49 def self.read_record(csv_data, config={ csv: nil }) label, sep = parse_config(config) header, *data = csv_to_array(csv_data, sep, label) csv_records = data.map {|row| convert_to_hash(header, row) } if label && label.index('|') return compose_inner_iteration_records(csv_records, label) end compose_record(csv_records, label) end
Private Class Methods
array_to_csv(records, col_sep)
click to toggle source
# File lib/ad_hoc_template/record_reader.rb, line 145 def self.array_to_csv(records, col_sep) # I do not adopt "records.map {|rec| rec.to_csv }.join", # because I'm not sure if it is sufficient for certain data or not. # For example, a field value may contain carriage returns or line # feeds, and in that case, improper handling of the end of record # would be damaging. CSV.generate(+'', col_sep: col_sep) do |csv| records.each {|record| csv << record } end end
compose_inner_iteration_records(csv_records, given_label, main_record={})
click to toggle source
# File lib/ad_hoc_template/record_reader.rb, line 105 def self.compose_inner_iteration_records(csv_records, given_label, main_record={}) outer_label, inner_label, key = ('#' + given_label).split(/\|/, 3) values = inner_iteration_records(csv_records, key) labels = inner_iteration_labels(outer_label, inner_label, values.keys) unless main_record[outer_label] main_record[outer_label] = values.keys.map {|k| { key => k } } end values.keys.each {|k| main_record[labels[k]] = values[k] } main_record end
compose_record(csv_records, label)
click to toggle source
# File lib/ad_hoc_template/record_reader.rb, line 95 def self.compose_record(csv_records, label) if label { '#' + label => csv_records } elsif csv_records.length == 1 csv_records[0] else csv_records end end
convert_to_hash(header, row_array)
click to toggle source
# File lib/ad_hoc_template/record_reader.rb, line 69 def self.convert_to_hash(header, row_array) {}.tap do |record| header.zip(row_array).each {|key, value| record[key] = value } end # if RUBY_VERSION >= 2.1.0: header.zip(row_array).to_h end
csv_compatible_format?(data)
click to toggle source
# File lib/ad_hoc_template/record_reader.rb, line 129 def self.csv_compatible_format?(data) iteration_blocks_count = data.values.count {|v| v.kind_of? Array } iteration_blocks_count.zero? || (iteration_blocks_count == 1 && data.size == 1) end
csv_to_array(csv_data, col_sep, label)
click to toggle source
# File lib/ad_hoc_template/record_reader.rb, line 89 def self.csv_to_array(csv_data, col_sep, label) array = CSV.new(csv_data, col_sep: col_sep).to_a array = array.transpose if !label || label == HEADER_POSITION::LEFT array end
find_sub_records(data)
click to toggle source
# File lib/ad_hoc_template/record_reader.rb, line 141 def self.find_sub_records(data) data.values.find {|v| v.kind_of? Array } end
hashes_to_arrays(data)
click to toggle source
# File lib/ad_hoc_template/record_reader.rb, line 135 def self.hashes_to_arrays(data) headers = data.max_by {|h| h.keys.size }.keys records = data.map {|record| headers.map {|header| record[header] } } records.unshift headers end
inner_iteration_labels(outer_label, inner_label, keys)
click to toggle source
# File lib/ad_hoc_template/record_reader.rb, line 123 def self.inner_iteration_labels(outer_label, inner_label, keys) keys.each_with_object({}) do |key, labels| labels[key] = [outer_label, inner_label, key].join('|') end end
inner_iteration_records(csv_records, key)
click to toggle source
# File lib/ad_hoc_template/record_reader.rb, line 117 def self.inner_iteration_records(csv_records, key) values = Hash.new {|h, k| h[k] = [] } csv_records.each {|record| values[record[key]].push record } values end
parse_config(config)
click to toggle source
# File lib/ad_hoc_template/record_reader.rb, line 76 def self.parse_config(config) case config when Symbol format, label = config, nil when String format, label = :csv, config when Hash format, label = config.to_a[0] end col_sep = COL_SEP[format || :csv] [label, col_sep] end