# frozen_string_literal: true require 'csv' require 'chronicle/utils/hash_utils' module Chronicle module ETL class CSVLoader < Chronicle::ETL::Loader include Chronicle::ETL::Loaders::Helpers::StdoutHelper register_connector do |r| r.identifier = :csv r.description = 'CSV' end setting :output setting :headers, default: true setting :header_row, default: true def records @records ||= [] end def load(record) records << record end def finish return unless records.any? # headers = filtered_headers(records) headers = gather_headers(records) csv_options = {} if @config.headers csv_options[:write_headers] = @config.header_row csv_options[:headers] = headers end csv_output = CSV.generate(**csv_options) do |csv| records.each do |record| csv << Chronicle::Utils::HashUtils.flatten_hash(record.to_h) .values_at(*headers) .map { |value| force_utf8(value) } end end # TODO: just write to io directly if output_to_stdout? write_to_stdout(csv_output) else File.write(@config.output, csv_output) end end private def gather_headers(records) records_flattened = records.map do |record| Chronicle::Utils::HashUtils.flatten_hash(record.to_h) end records_flattened.flat_map(&:keys).uniq end end end end