Nasty File Column Bug

I just fixed a nasty little bug in my FileColumn library, leading to a 0.1.1 release.

I had the following code in a helper method to generate an URL where you can access an uploaded file:

url = @request.relative_url_root.to_s
url << object.send("#{method}_options")["base_url"]
url << "#{method}/" 
url << object.send("#{method}_relative_path")

Looks pretty innocent, does it? What it made it even worse is that it worked in WebRick, but totally broke when running on Apache. After the first request, I’d only get “Application error”. So what happened?

In WebRick, @request.relative_url_root is nil, so to_s returns a new empty string object. On Apache, however, it is a string containing the “installation path” of your webapp. So to_s returns the string itself and now I modify this exact instance of the string. Unfortunately it is shared for performance reasons, so the next time I call @request.relative_url_to_root, I will get back the URL I just generated, which obviously is not a good idea…

Lesson learned: Be careful with String#<< as it modifies the string in place. Strings are not immutable as (for example) in Java.