Dynamically set a domain for a Rails asset host

I’ve been wanting to implement an asset host for my Rails app, looking over the API I saw that Rails’ asset_host only supported a single domain. I’m running multiple domains off one Rails app, so this would have been a problem. After a little research, I came up with a solution that would work for me.

I run this as a before_filter in my Application Controller.

# for my use, @site.domain returns the user's current
# domain. you should change this to whatever method
# you use to get the domain

class ApplicationController < ActionController::Base
before_filter :find_asset_host
 
private

  def find_asset_host
    ActionController::Base.asset_host = Proc.new { |source|
        asset_hosts = %w{icarus zeus aphrodite etc etc}
     
        # disable asset host for development
        if is_development?
          ""
        else
          "http://#{asset_hosts[rand(4)]}.#{@site.domain}"
        end
      }    
  end
 
end

Tags: , ,

7 comments

  1. Asset hosts support multiple domains: config.action_controller.asset_host = “assets%d.domain.com”

  2. off topic, but is that your S4??? if so, nice.

  3. It's really cool. Does it mean that I can hold more than 4 assets hosting server?

  4. You set your hosts in the hash.

  5. I really wouldn't recommend implementing this. From what I know, the randomized solution above will force assets to be downloaded 3+ times (once for each server) as a user cruises through your website. It will essentially render browser caching useless.

    Example:
    We're linking to logo.png in the header.
    Page 1: http://icarus.mycoolsite.com/images/logo.png
    Page 2: http://zeus.mycoolsite.com/images/logo.png
    Page 3: http://aphrodite.mycoolsite.com/images/logo.png

    Your browser will interpret this as 3 different files and download it once at Page 1 and again on Page 2 and again on Page 3. Imagine doing that with every asset on a page. This is way worse than having a single asset host.

    The real solution would be to conceive of a way to tie specific assets to specific hosts by filename or id or something.

  6. Then spend a little extra time to make it work…the following is my production code.

    def find_asset_host
    if APP_CONFIG['use_asset_servers'] == true
    ActionController::Base.asset_host = Proc.new { |source|
    asset_hosts = %w{icarus hades dionysus apollo zeus aphrodite ares poseidon}

    # disable asset host
    if is_development?
    “”
    else
    if source.starts_with?('/content')
    “http://#{asset_hosts[rand(8)]}.#{@site.domain}”
    else
    “http://assets.#{@site.domain}”
    end
    end
    }
    end
    end

  7. Then spend a little extra time to make it work…the following is my production code.

    def find_asset_host
    if APP_CONFIG['use_asset_servers'] == true
    ActionController::Base.asset_host = Proc.new { |source|
    asset_hosts = %w{icarus hades dionysus apollo zeus aphrodite ares poseidon}

    # disable asset host
    if is_development?
    “”
    else
    if source.starts_with?('/content')
    “http://#{asset_hosts[rand(8)]}.#{@site.domain}”
    else
    “http://assets.#{@site.domain}”
    end
    end
    }
    end
    end

Leave a comment