From 625f721bc43d8b50b76c425ceb5663a154e09393 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Mon, 1 Jun 2020 22:50:42 +0900 Subject: [PATCH] Add `undef: :replace` for `CSV.open` This PR adds `undef: :replace` option for `CSV.open`. `File.open` has `undef: :replace` option, but `CSV.open` does not. It would be convenient if `CSV.open` could have a shortcut by having `undef: :replace` option. --- lib/csv.rb | 7 +++++++ test/csv/interface/test_read.rb | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/lib/csv.rb b/lib/csv.rb index 4ffffe40..a06c92a1 100644 --- a/lib/csv.rb +++ b/lib/csv.rb @@ -960,6 +960,11 @@ def generate_line(row, **options) # open( filename, mode = "rb", **options ) # open( filename, **options ) # + # possible options elements: + # hash form: + # :undef => :replace # replace undefined conversion + # :replace => string # replacement string ("?" or "\uFFFD" if not specified) + # # This method opens an IO object, and wraps that with CSV. This is intended # as the primary interface for writing a CSV file. # @@ -1021,6 +1026,8 @@ def open(filename, mode="r", **options) # wrap a File opened with the remaining +args+ with no newline # decorator file_opts = {universal_newline: false}.merge(options) + options.delete(:undef) + options.delete(:replace) begin f = File.open(filename, mode, **file_opts) diff --git a/test/csv/interface/test_read.rb b/test/csv/interface/test_read.rb index 58ec188f..4b0f5e7e 100644 --- a/test/csv/interface/test_read.rb +++ b/test/csv/interface/test_read.rb @@ -125,6 +125,28 @@ def test_open_encoding_utf_8_with_bom end end + def test_open_with_undef_replace + # U+00B7 Middle Dot + CSV.open(@input.path, "w", encoding: Encoding::CP932, undef: :replace) do |rows| + rows << ["\u00B7"] + end + CSV.open(@input.path, encoding: Encoding::CP932) do |csv| + assert_equal([["?"]], + csv.to_a) + end + end + + def test_open_with_undef_replace_and_replace_string + # U+00B7 Middle Dot + CSV.open(@input.path, "w", encoding: Encoding::CP932, undef: :replace, replace: "X") do |rows| + rows << ["\u00B7"] + end + CSV.open(@input.path, encoding: Encoding::CP932) do |csv| + assert_equal([["X"]], + csv.to_a) + end + end + def test_parse assert_equal(@rows, CSV.parse(@data, col_sep: "\t", row_sep: "\r\n"))