Reputation: 382
I'm trying to remove all line break characters (\n and \r) from within column values on an outbound CSV before its sent. The most straightforward way appears to be with a CSV Converter - however, it doesn't seem to be working for me.
csv_options = {}
csv_options[:force_quotes] = true
csv_options[:col_sep] = "|"
CSV::Converters[:remove_newlines] = lambda{|s|
begin
s.tr("\n","").tr("\r","")
rescue ArgumentError
s
end
}
csv_options[:converters] = [:remove_newlines]
CSV.open(local_file.path, "wb", csv_options) do |csv|
...
When I test this, the other aspects of csv_options
(the :force_quotes
and :col_sep
) both work, but line breaks within fields still remain. Does anyone have any suggestions? Note that, for various reasons, I can't remove the linebreaks directly in the strings (or anywhere within the CSV.open
block itself), which is why I'm trying to use the converters.
EDIT: Sharpened up the code a bit based on other users' input, but with the same results. Code I'm using now is:
CSV.open(local_file.path, "wb",
:force_quotes => true,
:col_sep => "|",
:converters => lambda { |s| s.tr("\n\r","") }
) do |csv|
...
Upvotes: 2
Views: 916
Reputation: 2053
So, the issue is that you want to convert the output to a file and not the input. The :converters
option only handles converting input from a CSV file, it doesn't apply the conversions when writing out in CSV format.
If you really want this functionality you can monkey patch it in:
require 'csv'
class CSV
alias :old_init_separators :init_separators
def init_separators(options)
old_init_separators(options)
if options.delete(:remove_newlines)
old_quote = @quote
@quote = lambda do |field|
old_quote.call(String(field).tr("\r\n", ""))
end
end
end
end
CSV.open('test.csv', 'wb',
:force_quotes => true,
:col_sep => '|',
:remove_newlines => true) do |csv|
csv << ["A\r\nB", "C\r\nD"]
csv << ["E\r\nF", "G\r\nH"]
end
Note the addition of the :remove_newlines
option.
$ cat test.csv
"AB"|"CD"
"EF"|"GH"
Upvotes: 1