elabs/refile — pull request #64 by janko-m (2014-12-23 16:37:16+00:00)
Title: Speed up IO work

Utilizing `IO.copy_stream` was a bit difficult to implement, so I split it into multiple commits. Detailed argumentation for each commit is in their description, so I will just summarize here.

When we're copying IOs, we want to do it in the fastest and most memory efficient way possible. `IO.copy_steam` does just that. I learned about it from a RubyTapas (series about implementing the `tail` UNIX command), and Avdi Grimm said that in his personal benchmark "it performs close to an order of magnitude faster" than manual `#read` & `#write`.

Utilizing `IO.copy_stream` requires us to use real IO objects, so we have to remove the loose requirements of just responding to 4 methods (`#eof?`, `#read`, `#close` and `#size`). We don't lose anything by this, because I can't imagine people not using real IO objects. That means we also have to simplify the S3 implementation, which I find positive.

If find the S3 simplification justified because files will almost always have to be processed before displaying, meaning that they will have to be downloaded first. This downloading is now much more efficient because of `IO.copy_stream`. We also get a bonus that instead of streaming the file we could just use `#send_file`, which enables us to assign filenames like the documentation suggests.

I know this is quite a bit, but these changes were all intertwined so that's why they're together. I know that this breaks any backend whose `#open` method doesn't return an IO object. Let me know what you think.