Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby - Creating a file in memory

Tags:

io

ruby

csv

Is there anyway to write the following code in Ruby without writing the file to disk?

temp_file = 'path/to/file.csv'
users = [[email protected], [email protected]]

CSV.open(temp_file, "w") do |csv|
  csv << data_for_report
end

Reports.sendreport users temp_file

File.delete(temp_file)

The Reports.sendreport attaches a file and sends an email, so it needs to be a file...

like image 604
hirolau Avatar asked Jan 23 '13 20:01

hirolau


People also ask

How do you create a temp file in Ruby?

In any case, all arguments ( basename , tmpdir , mode , and **options ) will be treated as ::new. Creates a temporary file with permissions 0600 (= only readable and writable by the owner) and opens it with mode “w+”. The temporary file will be placed in the directory as specified by the tmpdir parameter.

What is file handling in Ruby?

It is a way of processing a file such as creating a new file, reading content in a file, writing content to a file, appending content to a file, renaming the file and deleting the file. Common modes for File Handling. “r” : Read-only mode for a file. “r+” : Read-Write mode for a file.


4 Answers

You could use Tempfile. Tempfile writes the file to disc, so it does not fit your request.

But I think Tempfile provides some features you need:

When a Tempfile object is garbage collected, or when the Ruby interpreter exits, its associated temporary file is automatically deleted.

Example:

require 'tempfile'
require 'csv'

data_for_report = [1,2,3,4]
temp_file = Tempfile.new('foo')

CSV.open(temp_file, "w") do |csv|
  csv << data_for_report
end
like image 197
knut Avatar answered Nov 03 '22 21:11

knut


Try one of the mmap gems. If the library only takes a filename, that's your option.

If it can accept a file-like object, however, you can use a StringIO.

You might consider changing whatever Reports is, making it more general-purpose. It depends on what it's using to create its mail message–this might be trivial.

like image 33
Dave Newton Avatar answered Nov 03 '22 20:11

Dave Newton


With your current code that's not possible, if your code would use file pointers/handles instead you can do the following:

require 'csv'
require 'stringio'

data_for_report = [1,2,3,4]
temp_file = StringIO.new # creates a fake file as string.

CSV.new(temp_file, "w") do |csv|
  csv << data_for_report
end

The key problem why it isn't working for your usecase is the line Reports.report users temp_file

If that accepts a handle instead of a string it'll work.

See also this SO: https://stackoverflow.com/a/19110958/887836

like image 30
Alexander Oh Avatar answered Nov 03 '22 19:11

Alexander Oh


temp_file = CSV.generate do |csv|
  csv << data_for_report
end

Reports.sendreport users temp_file
like image 23
Gregory Ray Avatar answered Nov 03 '22 19:11

Gregory Ray