Search code examples
ruby-on-railsrubyioerrortemporary-files

Read data from newly written TempFile doesn't work? IOerror closed stream in Ruby on Rails


I am implementing in Ruby on Rails, and i have 2 views. In my first view i read in a file and show the first rows (this works fine), then in my second view ( in the method in the controller ) i write a temporary file. Just the same. And i want to show the content of this temporary file again. But this doesn't work, I always get the error :

IOError in Project importerController#result

closed stream

this is my code in the controller, behind the first view i do:

 tmpfile = Tempfile.new("tempfile")
    if tmpfile     
      tmpfile.write(@samples)
      tmpfile.close
      tmpfilename = File.basename(tmpfile.path)
      tmpfilenametest = tmpfilename
      if !$tmpfiles
        $tmpfiles = Hash.new
      end
      $tmpfiles[tmpfilename] = tmpfile
    else
      flash[:error] = "Cannot save import file."
      return
    end
    @path = tmpfile.path
    session[:importer_tmpfile] = tmpfilename
   end 

and then in my next view , I want to read this file by:

 tmpfilename = session[:importer_tmpfile]
      i = 0
      sample_count = 5

      if tmpfilename
      tmpfile = $tmpfiles[tmpfilename]
      if tmpfile == nil
        flash[:error] = "Tijdelijk bestand bestaat niet!"
        return
      end
    end


    fields_map = params[:fields_map]
      attrs_map = fields_map.invert

      @parsed_tempfile=CSV::Reader.parse(tmpfile)
       @sampletemp = []
     @parsed_tempfile.each  do |row| 

          @sampletemp[i] = row  

        i = i+1  

     end

In this view i just want to show it, i just have:

<ul>
<% @sampletemp.each do |x| %>
<li>
<%= x %>
</li>
<% end %>
</ul>

Does anybody see what i am doing wrong? Thanks in advance!


Solution

  • AFAIK, a Tempfile only lasts until you close it - then it is no longer valid. If you want to actually save data in a file that sticks around after you close it - then you'll need to use a real File.

    Edit; According to our discussion, I don't think you need a tempfile at all. You are just displaying parts of the file-data that the user has uploaded for you. You don't need a real file object for that (tempfile or otherwise).

    The user uploads a "file" and you can parse the CSV (as you've done) then afterwards you can just treat it as an array of strings. Save it in an @var like "@csv_lines" and in your views access the array @csv_lines however you need to.