受け入れられた答えは実際には質問に答えていないので、私は有用な例を挙げたいと思いました。
まず、http://ruby-doc.org/stdlib-1.9.3/libdoc/csv/rdoc/CSV.htmlのドキュメントを見ると、メソッド名にカーソルを合わせると表示されdump
ますclick to show source
。これを行うと、メソッドが、渡した最初のオブジェクトdump
を呼び出そうとしていることがわかります。csv_headers
ary_of_objs
obj_template = ary_of_objs.first
...snip...
headers = obj_template.csv_headers
その後、メソッドがcsv_dump
で各オブジェクトを呼び出し、 :ary_of_objs
を渡すことがわかります。headers
ary_of_objs.each do |obj|
begin
csv << obj.csv_dump(headers)
rescue NoMethodError
csv << headers.map do |var|
if var[0] == @
obj.instance_variable_get(var)
else
obj[var[0..-2]]
end
end
end
end
array_of_objs
したがって、これら2つの方法に対応するには、の各エントリを拡張する必要があります。Hash
を取り、ハッシュキーをCSVヘッダーとして返し、ヘッダーに基づいて各行をダンプできるラッパークラスの例を次に示します。
class CsvRowDump
def initialize(row_hash)
@row = row_hash
end
def csv_headers
@row.keys
end
def csv_dump(headers)
headers.map { |h| @row[h] }
end
end
ただし、もう1つ問題があります。このdump
メソッドは、CSVファイルの先頭のヘッダーの前に余分な行を書き込みたいので、このコードが先頭にあるためにこのメソッドを呼び出す場合、それをスキップする方法はありません。
# write meta information
begin
csv << obj_template.class.csv_meta
rescue NoMethodError
csv << [:class, obj_template.class]
end
そこから''を返してもCsvRowDump.csv_meta
、解析でヘッダーが必要な空白行になります。代わりにdump
、その行を書いて、後で。を呼び出すときにそれを削除しましょうdump
。この例では、すべて同じキー(CSVヘッダーになります)を持つハッシュの配列があることを前提としています。
@rows = @hashes.map { |h| CsvRowDump.new(h) }
File.open(@filename, "wb") do |f|
str = CSV::dump(@rows)
f.write(str.split(/\n/)[1..-1].join("\n"))
end