I want to make a method that writes some CSV output to a filename if given and stdout if not given.
It seems like I need to treat my calls to CSV
differently depending on if it's a file or to stdout, but I'd really like to treat the output stream z
as something I can write to and not have to whether it's a file on disk or the stdout stream.
Is this possible?
Below is my attempt and errors:
require 'csv'
require 'pathname'
require 'csv'
require 'pathname'
def write_to_csv_or_stdout foo, bar, z=nil
z = Pathname.new(z) if z
z ||= $stdout
res = [[foo, bar, "baz"]]
CSV(z) do |csv|
res.each do |row|
csv << row
end
end
end
write_to_csv_or_stdout "foo", "bar"
# foo
# bar
#=> foo,bar,baz
# write_to_csv_or_stdout "foo", "bar", "baz"
# (NoMethodError)
This works for stdout and filenames.
It uses
$stdout.dup
to be able to closeio
without closing$stdout
.One solution would be not to use only the Pathname object since it isn't an IO object.
If you open the file then you can use it the same way as you would use the stdout object.
I'd use a helper method:
This can be used instead of
CSV(...)
: