Sha256: cd1818be5a5a68ba8a8ea65aeab04d3e3ac79eb4ed4c483103387811b3da71b2

Contents?: true

Size: 1.55 KB

Versions: 1

Compression:

Stored size: 1.55 KB

Contents

# frozen_string_literal: true

require 'csv'
require 'stream_lines/reading/stream'

module StreamLines
  module Reading
    class CSV
      # NOTE: (jdlubrano)
      # I suspect that these options are not used terribly frequently, and each
      # would require additional logic in the #each method.  Rather than
      # attempting to implement sensible solutions for these options, I am
      # choosing to explicitly ignore them until there is enough outcry to
      # support them.
      IGNORED_CSV_OPTIONS = %i[
        return_headers
        header_converters
        skip_lines
      ].freeze

      include Enumerable

      def initialize(url, **csv_options)
        @url = url
        @csv_options = accepted_csv_options(csv_options)

        encoding = @csv_options[:encoding] || Encoding.default_external
        @stream = Stream.new(url, encoding: encoding)
      end

      def each(&block)
        @stream.each_with_index do |line, i|
          next assign_first_row_headers(line) if i.zero? && first_row_headers?

          block.call(::CSV.parse_line(line, **@csv_options))
        end
      end

      private

      attr_reader :url

      def first_row_headers?
        @csv_options[:headers] == true
      end

      def assign_first_row_headers(first_line)
        header_row = ::CSV.parse_line(first_line)
        @csv_options[:headers] = header_row
      end

      def accepted_csv_options(csv_options)
        csv_options.transform_keys(&:to_sym)
                   .delete_if { |key, _value| IGNORED_CSV_OPTIONS.include?(key) }
      end
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
stream_lines-0.4.0 lib/stream_lines/reading/csv.rb