CSVのデータをDBに取り込みたく、ActiveRecordを使いたい時。最近よく書くので
require 'csv'
def import_row(row)
# something to do
return '必須項目がない' if row['必須な列'].blank? # 要 ActiveSupport
nil
end
if ARGV[0].nil?
puts 'input csv filename on arguments'
elsif !File.exist?(ARGV[0])
puts "#{ARGV[0]} is not found"
else
CSV.foreach(ARGV[0],
headers: true,
encoding: 'BOM|UTF-8',
header_converters: Proc.new { |h| h.strip },
skip_blanks: true) do |row|
result = import_row(row)
puts result + ',' + row.to_csv if result
end
end
- ファイルはコマンドライン引数から受け取る。めんどくさいので。
- 行の処理はメソッドに分ける。これで、エラーメッセージを出して
next
みたいなことをしなくてよくなる。後置ifの強みが活かせるように思う。 - 例外的な行はメソッド内でチェックし、エラー行として出す。メッセージと元の行を出して有効活用する。
$INPUT_LINE_NUMBER
で行数を出すのも良い。ファイル出力もできるが、一旦は標準出力のリダイレクトで解決。場合により。 -
headers: true
で、ヘッダが日本語でもrow['列名']
でアクセスできる。ただ、BOMが付いているとrow.header[0]
にもBOMがついてきてアクセスできないとかトラブルもあり、ファイルを見つつやる必要はある。 - BOMがついてる場合は
encoding: 'BOM|UTF-8'
で解決。 -
header_converters: Proc.new { |h| h.strip }
でヘッダから空白が取れる、といった形で加工もできる。