Rails Fix Slow Loads in Development when Images Missing

I have found it useful to populate my local development database with data from our production server in order to be able to get good test coverage. However, a perpetual problem I’ve had with this approach is that it introduces an environment where sometimes images are available and sometimes they aren’t (the database knows about all the images, but some were uploaded locally, some reside on our main servers, and some are on S3).

What I’ve found is that even though Rails doesn’t give exceptions when it finds missing images, it does start to get painfully slow. Each missing image it has to process usually takes about 2 seconds. On pages with 5-10 missing images, the wait could be quite painful.

So I finally got fed up yesterday and wrote a hacky patch to get around this problem. Here it is:

def self.force_image_exists(image_location)
 default_image = "/images/dumpster.gif"
 if(image_location && (image_location.index("http") || File.exists?(RAILS_ROOT +  "/public" + image_location.gsub(/\?.*/, ''))))
  image_location
 else
  default_image
 end
end

This function is part of a utility class (named “UtilityGeneral”) that we use for various miscellaneous tasks. I call this method from a simple mixin:

if RAILS_ENV == 'development'
 module ActionView 
  module Helpers #:nodoc: 
   module AssetTagHelper
   # replace image tag
   def path_to_image(source)
     original_tag = ImageTag.new(self, @controller, source).public_path
     UtilityGeneral.force_image_exists(original_tag)
    end
   end
  end
 end
end

If anyone else works locally with images that may or may not exist, this wee patch should come in handy to save you from load times of doom on pages that are missing images. It just subs in an alternate image when the real image doesn’t exist locally.

P.S. When I grow up, I want a blog about coding that lets me paste code.
P.S.S. 4/10: I grew up!

5 Replies to “Rails Fix Slow Loads in Development when Images Missing”

  1. Hey Ben,

    Good idea, but I think there are a couple typos in the example. From what I can tell, it looks like the snippet would use the trash_can image every time, rather than only using it when original_tag can’t be found.

    Also, default_image (the else case) isn’t declared in the snippet.

  2. I do this using mod_rewrite, which should be a bit quicker. If a path looks like an image, and it’s not found, then rewrite it to a default image:

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule _small.(jpg|png)$ /images/photo_unavailable_small.png [L]

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule _large.(jpg|png)$ /images/photo_unavailable_large.png [L]

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^/images/products /images/photo_unavailable_large.png [L]

    These rules could definitely be more efficient – there’s no need to do the file exists test in every case, and so often!

  3. This is my example:

    ServerName localhost
    ServerAlias modcloth
    AllowEncodedSlashes on # 404-not found error on a page wherein which the URL has %2F and it needs to be decoded as /

    # Fake productshots to avoid slow 404 on every product image.
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule _carousel.(jpg|png)$ /home/mario/public_html/fake_productshots/PRODUCT_carousel.jpg [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule _category.(jpg|png)$ /home/mario/public_html/fake_productshots/PRODUCT_category.jpg [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule _quicklook.(jpg|png)$ /home/mario/public_html/fake_productshots/PRODUCT_quicklook.jpg [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule _thumb.(jpg|png)$ /home/mario/public_html/fake_productshots/PRODUCT_thumb.jpg [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule _tiny.(jpg|png)$ /home/mario/public_html/fake_productshots/PRODUCT_tiny.jpg [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule .(jpg|png)$ /var/www/home/mario/public_html/fake_productshots/PRODUCT.jpg [L]

    # To use Rails Mongrel cluster as proxy
    ProxyPass / balancer://mongrelcluster/
    ProxyPassReverse / balancer://mongrelcluster/
    ProxyPreserveHost on

  4. If anyone’s trying to make this work under Rails 2.3, here’s what I did, put everything in an Initializer :

    # originally found at https://www.williambharding.com/blog/rails/rails-fix-slow-loads-in-development-when-images-missing/
    if RAILS_ENV == ‘development’
    module ActionView
    module Helpers #:nodoc:
    module AssetTagHelper
    def path_to_image(source)
    original_tag = compute_public_path(source, “images”)
    # Create the file below or simply point it to your own placeholder
    default_image = “/images/404_dev_image.jpg”
    if(original_tag && (original_tag.index(“http”) || File.exists?(RAILS_ROOT + “/public” + original_tag.gsub(/?.*/, ”))))
    original_tag
    else
    default_image
    end
    end
    end
    end
    end
    end

Leave a Reply to Anthony Cancel reply

Your email address will not be published. Required fields are marked *