Skip to main content

Using CarrierWave with a dynamic fog host and a CDN

Another simple case of "this took longer than it takes to look up this issue on Google" :)

CarrierWave is a fantastic and well supported ruby gem for managing images, including support for cloud storage like Amazon.

Whether or not you use CarrierWave on the cloud, you almost always want to put your user-uploaded images behind a CDN.  There are many CDNs available, including Amazon's CloudFront, Fastly.com, CacheFly, Akamai, etc, and comparing them is outside the scope of this article. 

Because browsers, especially older, are limited in how many connections they will establish to a single host, it is sometimes beneficial to have images load from several alternating URLs, for example:
http://cdn-0.wanelo.com
http://cdn-1.wanelo.com
http://cdn-2.wanelo.com

etc...

CarrierWave supports fog_host variable which can be set to either a string (a static hostname), or a lambda (if for example a randomized string is desired) and the usage is well described here.

Unfortunately, due a bug that is not yet fixed (and unclear if it will be), you currently can not use the file object directly inside the lambda as it's shown in the examples. 

If you actually want to use the "file" object inside the fog_host proc in any way, then fog_host must be a double-lambda, because the first lambda gets called by the accessor created in Configuration class. The second is then called in public_url instance method.

Here is the configuration we ended up using, which works perfectly:
    config.fog_host = lambda do
      lambda do |file|
        host_number = file.path.sum % 4
        "cdn-s3-%d.ourdomain.com" % host_number
      end
    end
The advantage of this approach, is that with several CDN hosts (which are useful to increase speed of browser's parallel download of images), this allows you to generate a consistent URL for each file instead of a random one. So a file with name "image.jpg" will always generate "cdn-s3-2.ourdomain.com" because of simple assignment:
"image.jpg".sum % 4
=> 2
Thanks to Jay Phillips for the tricky solution to this one.

Comments

Popular posts from this blog

Car or Auto Make-Model-Year Database : For Breakfast

Make Model What?If you like me were tasked with loading a database of recent car makes/models/years, you would start by looking on the web and seeing if someone else just has it out there, readily available, hopefully for free, but perhaps for a tiny nominal fee.?If only it was that simple... I looked and looked, and couldn't find anything that would fit the above requirements. So I thought, who would know about US car models better than Kelly Blue Book? So I went on their site, and sure enough they have a javascript file that lists all known to them makes and models of used cars. Since the file is public, I figured it's not really "evil" if I scrape and parse it for my own benefit. Disagree? Have a better source? Then leave a comment.Anyway, to cut the long story short, I'm hoping to save a day or so to someone else who may, like me, be looking for this information. The ruby module shown below retrieves and parses the javascript from KBB site into a Ruby da…

Mac OS-X tips: How to run SSHD on an alternative port

This tip falls into one of those "I had to spend more than 10 minutes looking for an answer" category, so it's a worthwhile subject for a quick blog post. Why Run SSH? Running SSH on Mac OS-X allows you to login to your machine remotely, and also copy file securely via SCP command to and from your Mac OS-X host. But I am behind my own $50 router/firewall. Can I still connect to my computer from outiside?Yes. Most off the shelf routers and firewalls will allow you to do two things that are needed for this: Assign a permanent IP address to your Mac on a local network (see your router documentation for more details) Create a port forwarding rule on your router. Eg - any request to port 22 on your external IP (provided by your router) can be routed to the specific IP address of your Mac. Exact specifics on this configuration are once again available in your router documentation. Most off the shelf routers support this, including basic Netgear and D-Link. So let'…

Why I Like PostgreSQL

Today I gave a short presentation at work about PostgreSQL, and why I much prefer it to MySQL.

PostgreSQL vs MySQL: Eternal Battle
I may be misreading this, but it seems that there is a recent trend within startups to move away from MySQL, probably thanks to folks like Heroku on one side (who use PostgreSQL to the extreme, and help and contribute to it's development), vs folks like Oracle on the other side, tainting the "open source pureness" of MySQL :)

At my work we currently use a mid-sized MySQL 5.1 Percona instance, which is holding up quite well I must admit. Both PostgreSQL and MySQL have definitely converged to cover most features that people want, but my leaning is still towards PostgreSQL. I just agree with it's focus on data integrity, recovery, constraints, extensibility, while some of the early decisions in MySQL's design do not agree with me at all (like truncating long strings, 1/0 instead of booleans, ambiguous group by, etc). I think that data …