Sha256: a9702bdfda518d91e7ec215ecfdf860c5ec1a9dbf33c195d2028b78ff8ea22aa

Contents?: true

Size: 1.27 KB

Versions: 2

Compression:

Stored size: 1.27 KB

Contents

require 'csv'

module AsCSV
  class CSVBuilder
    attr_reader :records, :options, :csv_options

    def initialize(records, options={})
      @records = Array(records)
      @options = options
      @csv_options = options.delete(:csv_options) || {}
      validate
    end

    def to_csv
      rows.collect { |row| CSV.generate_line(row, **csv_options) }.join
    end

    private

      def rows
        @rows ||= [headers] + data_rows
      end

      def headers
        @headers ||= csv_hashes.collect(&:keys).flatten.uniq
      end

      def data_rows
        @data_rows ||= csv_hashes.collect { |csv_hash| data_row csv_hash }
      end

      def validate
        validate_members
        validate_hashes
      end

      def validate_members
        if records.any? { |r| not r.respond_to? :as_csv }
          raise TypeError, 'Some elements do not respond to :as_csv'
        end
      end

      def validate_hashes
        csv_hashes.each do |hash|
          raise TypeError, "expected as_csv to return Hash" unless hash.is_a? Hash
        end
      end

      def csv_hashes
        @csv_hashes ||= records.collect { |r| r.as_csv(options) if r.respond_to? :as_csv }.compact
      end

      def data_row(csv_hash)
        headers.collect { |header| csv_hash[header] }
      end
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
as_csv-3.0.1 lib/as_csv/csv_builder.rb
as_csv-3.0.0 lib/as_csv/csv_builder.rb