I often use Ruby’s
Tempfile
class when generating files in Rails for download. But something went wrong in the Rails 3.2.11 update.Here is the code I normally use (as per the Tempfile documentation):
Ruby programs are a sequence of expressions. Each expression is delimited by semicolons(;) or newlines unless obviously incomplete (e.g. Trailing ‘+’). Backslashes at the end of line does not terminate expression.
In short, create a temp file, stream the data to it in the report class, then send the file to the user. Ensure the file is closed and deleted after. Prior to Rails 3.2.11, this worked fine.
The problem after the 3.2.11 update is that the
temp.unlink
was happening before the file got sent (or maybe while it was being sent), leading to blank or corrupted files.It turns out, the
temp.unlink
is not necessary any more. As long as you close a Tempfile using temp.close
, Ruby’s Garbage Collector will delete the file for you, once it no longer needs it. Which means that the send_file
will have a file available to send. I monitored my temp folder and it does indeed do this.So, remove the
temp.unlink
line in Rails 3.2.11 projects, and ignore the documentation. You can now generate and send files from Rails again.Follow the author as @hiltmon on Twitter or @hiltmon on App.Net.
Posted by3 years ago
Archived
What are you preferred way of handling binary storage in Rails apps?
I have experience with several solutions that I all dislike in different ways:
- Shipping them to Rackspace Cloudfiles via Fog / CarrierWave. This one is a pain, because the Rackspace API is slow and the official ruby libraries (Fog) are obscenely fat. It pulls in a million sub gems for various storage providers. I mean, c'mon:
From gemfile.lock
Update: This point is somewhat refuted. Fog can be loaded with the Rackspace adapter alone. Use 'fog-rackspace' instead of 'fog' in Gemfile. However, Rackspace remains slooooow for non-read operations.
- Storing them on disk on the server. This one is easy to work with, doesn't require a bunch of libraries and it's very fast. Offsite backups are easy to schedule and they are fast and flexible with tools like Rsync. However, it ties your application to just one machine effectively preventing a redundant setup and making your application server more important than it deserves to be. Finally, it imposes (linearly expanding) storage requirements on your application server, which is quite inconvenient.
- Storing them in the (postgres) database. This one is easy to work with and prevents your application server from becoming a loner. However, it makes database backups more tedious and it you like to do a nightly dumps it produces a growing pile of identical data, where you would ideally prefer the incremental nature of tools like Rsync with file versioning. Finally this solution, unless you want to do something different, means your Rails app will always have to act as a transport between the database and the web server. Not always cool.
My ideal solution would be one that is:
- hosted
- cheap
- fast
- has an official ruby rest client with a rich, fast and intuitive API.
- offers file versioning with an API and/or UI to easily configure retention policies globally, for a particularly folder and a for particular file.
- reasonable security model with easy issuing of app tokens/api keys.
- ability to make files/folders/containers public and an ability to configure http header (policies?) for those.
- is fast to register, set up and implement. (time from signup to working ruby client must be less than 30 minutes, including setting up a credit card)
Basically the API should look something like:
I must confess that I have not bothered to explore the vast amount of options that Fog seems to support, so out of laziness, please share your preferences and why you prefer them.
15 comments