views:

36

answers:

2

My application accepts file uploads, with some metadata being stored in the DB, and the file itself on the file system. I am trying to make the metadata visible in the application before the file upload and post-processing are finished, but because saves are transactional, I have had no success. I have tried the callbacks and calling create_or_update() instead of save(), all to no avail. Is there a way to do this without re-writing the guts of ActiveRecord::Base? I've even attempted naming the method make() instead of save(), but perplexingly that had no effect.

The code below "works" fine, but the database is not modified until everything else is finished.

def save(upload)

uploadFile = upload['datafile']
originalName = uploadFile.original_filename
self.fileType = File.extname(originalName)

create_or_update()

# write the file
File.open(self.filePath, "wb") { |f| f.write(uploadFile.read) }
begin
  musicFile = TagLib::File.new(self.filePath())
  self.id3Title = musicFile.title
  self.id3Artist = musicFile.artist
  self.id3Length = musicFile.length
 rescue TagLib::BadFile => exc
    logger.error("Failed to id track: \n #{exc}")
end

if(self.fileType == '.mp3')
  convertToOGG();
end
create_or_update()

end

Any ideas would be quite welcome, thanks.

+1  A: 

Have you considered processing the file upload as a background task? Save the metadata as normal and then perform the upload and post-processing using Delayed Job or similar. This Railscast has the details.

John Topley
+1  A: 

You're getting the meta-data from the file, right? So is the problem that the conversion to OGG is taking too long, and you want the data to appear before the conversion?

If so, John above has the right idea -- you're going to need to accept the file upload, and schedule a conversion to occur sometime in the future.

The main reason why is that your rails thread will process the OGG conversion and can't respond to any other web-requests until it's complete. Blast!

Some servers compensate for this by having multiple rails threads, but I recommend a background queue (use BJ if you host yourself, or Heroku's background jobs if you host there).

Jesse Wolgamott