class CSV::Writer

Attributes

headers[R]
lineno[R]

Public Class Methods

new(output, options) click to toggle source
# File lib/csv/writer.rb, line 13
def initialize(output, options)
  @output = output
  @options = options
  @lineno = 0
  prepare
  if @options[:write_headers] and @headers
    self << @headers
  end
end

Public Instance Methods

<<(row) click to toggle source
# File lib/csv/writer.rb, line 23
def <<(row)
  case row
  when Row
    row = row.fields
  when Hash
    row = @headers.collect {|header| row[header]}
  end

  @headers ||= row if @use_headers
  @lineno += 1

  line = row.collect(&@quote).join(@column_separator) + @row_separator
  if @output_encoding
    line = line.encode(@output_encoding)
  end
  @output << line

  self
end
rewind() click to toggle source
# File lib/csv/writer.rb, line 43
def rewind
  @lineno = 0
  @headers = nil if @options[:headers].nil?
end

Private Instance Methods

prepare() click to toggle source
# File lib/csv/writer.rb, line 49
def prepare
  @encoding = @options[:encoding]

  prepare_header
  prepare_format
  prepare_output
end
prepare_format() click to toggle source
# File lib/csv/writer.rb, line 85
def prepare_format
  @column_separator = @options[:column_separator].to_s.encode(@encoding)
  row_separator = @options[:row_separator]
  if row_separator == :auto
    @row_separator = $INPUT_RECORD_SEPARATOR.encode(@encoding)
  else
    @row_separator = row_separator.to_s.encode(@encoding)
  end
  quote_character = @options[:quote_character]
  quote = lambda do |field|
    field = String(field)
    encoded_quote_character = quote_character.encode(field.encoding)
    encoded_quote_character +
      field.gsub(encoded_quote_character,
                 encoded_quote_character * 2) +
      encoded_quote_character
  end
  if @options[:force_quotes]
    @quote = quote
  else
    quotable_pattern =
      Regexp.new("[\r\n".encode(@encoding) +
                 Regexp.escape(@column_separator) +
                 Regexp.escape(quote_character.encode(@encoding)) +
                 "]".encode(@encoding))
    @quote = lambda do |field|
      if field.nil?  # represent +nil+ fields as empty unquoted fields
        ""
      else
        field = String(field)  # Stringify fields
        # represent empty fields as empty quoted fields
        if field.empty? or quotable_pattern.match?(field)
          quote.call(field)
        else
          field  # unquoted field
        end
      end
    end
  end
end
prepare_header() click to toggle source
# File lib/csv/writer.rb, line 57
def prepare_header
  headers = @options[:headers]
  case headers
  when Array
    @headers = headers
    @use_headers = true
  when String
    @headers = CSV.parse_line(headers,
                              col_sep: @options[:column_separator],
                              row_sep: @options[:row_separator],
                              quote_char: @options[:quote_character])
    @use_headers = true
  when true
    @headers = nil
    @use_headers = true
  else
    @headers = nil
    @use_headers = false
  end
  return unless @headers

  converter = @options[:header_fields_converter]
  @headers = converter.convert(@headers, nil, 0)
  @headers.each do |header|
    header.freeze if header.is_a?(String)
  end
end
prepare_output() click to toggle source
# File lib/csv/writer.rb, line 126
def prepare_output
  @output_encoding = nil
  return unless @output.is_a?(StringIO)

  output_encoding = @output.internal_encoding || @output.external_encoding
  if @encoding != output_encoding
    if @options[:force_encoding]
      @output_encoding = output_encoding
    else
      compatible_encoding = Encoding.compatible?(@encoding, output_encoding)
      if compatible_encoding
        @output.set_encoding(compatible_encoding)
        @output.seek(0, IO::SEEK_END)
      end
    end
  end
end