Ruby - Creating a file in memory

14,968

Solution 1

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.

Solution 2

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

Solution 3

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

Solution 4

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

Reports.sendreport users temp_file
Share:
14,968

Related videos on Youtube

hirolau
Author by

hirolau

Updated on June 06, 2022

Comments

  • hirolau
    hirolau almost 2 years

    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...

    • quandrum
      quandrum over 11 years
      So you want a string of comma separated values? Do you need the csv at that point? Could you join your columns with commas, and your rows with newlines?
    • hirolau
      hirolau over 11 years
      Ohh, the sendreport function sends a mail with a csv-file attached. So I really need it to be a file...
    • quandrum
      quandrum over 11 years
      Are you saying the sendreport method reads the file from disk?
    • hirolau
      hirolau over 11 years
      Correct.. It reads a file from disc and attaches it to an email. The question now is if there is anyway to save the file, as a file, in memory.
    • quandrum
      quandrum over 11 years
      If you can't change Reports, then you probably are doing it the right way. It's probably more trouble than it's worth to get a section of memory to pretend it's a disk so Reports can read from it.
  • hirolau
    hirolau over 11 years
    I will look into StringIO, think that might be what I am looking for... Reports.sendreport is really just my own wrapper on the gmail gem, so I am not really sure if i need a real if or if StringIO will work.
  • hirolau
    hirolau over 11 years
    It is one step closer.. Thank you!
  • GMA
    GMA over 10 years
    Note that it's Tempfile, not TempFile.
  • vovan
    vovan over 4 years
    The link to Ruby doc is broken