I’ve had this before so I should have learnt my lesson. But I didn’t.

I had a site, inherited from another developer, that was migrated to a new server.

The other developer sent me the images associated with the site and I dutifully copied them over. I took a look - lots of “missing image” place-holders, but as this was a work in progress, in a database of thousands of items, I didn’t know what should be there and shouldn’t.

So I asked the other developer to check things over.

No - there should be much more than that” he said.

But look - they are there - in the correct folder on the server!” I replied.

You’re right, ” he said, “but why aren’t they on the site?

It turns out that the code for deciding whether to show the product image or the place-holder looked something like this (with superfluous guff removed):

if File.exists?("#{RAILS_ROOT}/public#{product_image(img, true)}") 
  "<img src="http://blog.3hv.co.uk/wp-admin/#{product.image_filename}" />"
else
  "<img src="http://blog.3hv.co.uk/images/products/image_missing.jpg" />"
end

I spent a while playing around, using script/console on the server (a truly fantastic tool). I asked it to generate the image tag for a given product - it returned exactly what I was expecting. I looked at the equivalent page in the application - it returned the image missing place-holder. But mongrel was running as the same user as script/console - there couldn’t be a permissions issue could there?

Then I remembered …

  • on my dev box, in console and/or test suites, RAILS_ROOT returns an absolute path
  • on my dev box, in mongrel, RAILS_ROOT returns an absolute path
  • on a typical Ubuntu server, in console and/or test suites, RAILS_ROOT returns an absolute path
  • on a typical Ubuntu server, in mongrel, RAILS_ROOT returns a relative path

That was the issue - the file system was getting confused as mongrel gave it a relative path for RAILS_ROOT (ignoring the fact that it should be able to resolve it, no matter how many double dots there were). And even worse, things appeared to be working fine until it was deployed to the webserver.

The fix is simple - add the following to your application controller:

helper_method :rails_root
def rails_root
  File.expand_path RAILS_ROOT
end 

and then replace all instances of RAILS_ROOT within your controllers, views and helpers with rails_root. Problem solved.

Posted on April 28th, 2008 | filed under Brightbox, Deployment, Rails, Ruby | Trackback |

Leave a Reply

You must be logged in to post a comment.