LoginSignup
3
1

More than 3 years have passed since last update.

Ruby 2.6 から CSV の空行のパース結果が変わった

Last updated at Posted at 2019-10-08

Ruby で CSV を処理するときに、空行を無視するために empty? を使って下記のように書いていました。

require "csv"

CSV.foreach("foo", headers: :first_row) do |row|
  next if row.empty?
  p row
end

headers を指定した場合、行は CSV::Row で表現されますが、Ruby 2.6 からは CSV::Row#empty?false を返すようです。

#!/bin/sh

RBENV_VERSION=2.5.1 ruby -rcsv <<EOS
CSV.parse("\n", headers: %w(a)) do |row|
  p row.empty? # true
end
EOS

RBENV_VERSION=2.6.4 ruby -rcsv <<EOS
CSV.parse("\n", headers: %w(a)) do |row|
  p row.empty? # false
end
EOS

p row などでみてみると、2.5 ではフィールドの情報を持っていないのに対し、2.6 ではフィールドの情報を持っています。

#!/bin/sh

RBENV_VERSION=2.5.1 ruby -rcsv <<EOS
CSV.parse("\n", headers: %w(a)) do |row|
  p row # #<CSV::Row>
  p row.to_a # []
  p row.to_hash # {}
end
EOS

RBENV_VERSION=2.6.4 ruby -rcsv <<EOS
CSV.parse("\n", headers: %w(a)) do |row|
  p row # #<CSV::Row "a":nil>
  p row.to_a # [["a", nil]]
  p row.to_hash # {"a"=>nil}
end
EOS

ドキュメント には、empty? などは Array に delegate されると記載があります。上記のように 2.6 では to_a の返り値が空ではないので empty?false を返すようです。

空行の読み飛ばしは CSV::Row#empty? を使うのではなく、CSV.new 等のオプションに skip_blanks: true を指定するのがよさそうです (2.5, 2.6 とも)。

3
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1