Monday, August 06, 2007

FragmentFu - Fun with Fragments

First, please read the Advanced Rails Caching.. On the Edge for a primer on ESI, caching, and fragments.
To get started developing with ESI, I'm going to walk through a simple tutorial building an ESI enabled Rails application.
Get Mongrel-ESI
Find the latest mongrel ESI here:

(Does anyone have a better solution of ruby projects hosted on Google Code? )

Install Mongrel ESI

sudo gem install mongrel-esi-0.0.5.gem

Create a new rails application (Currently using rails 1.2.3)

rails fragment_fu_demo

create app/controllers
create app/helpers
create app/models

cd fragment_fu_demo

Create a home page for your application

Delete the public/index.html page

rm public/index.html

Edit the config/routes.rb and uncomment the following line:

map.connect '', :controller => "welcome"

Create a welcome controller

./script/generate controller welcome index

Install the FragmentFu plugin
./script/plugin install

Start your application


visit http://localhost:3000 in your browser. You should see a "Welcome#index" page.

Start MongrelEsi
From the command line, run:

mongrel_esi start
** Starting Mongrel listening at

visit http://localhost:2000 in your browser. You should see a "Welcome#index" page.

Create a fragment to cache
Edit the app/controllers/welcome_controller.rb
Add an action called now
def now
render :text => "#{} is #{} nano-seconds"

Edit the app/views/welcome/index.html.erb and replace with the following:

<p><%= render :esi => "/welcome/now" %></p>

Page without ESI parsing
visit http://localhost:3000 and you should see: "Time:" in the browser. If you view the source, you'll see

<p><esi:include src="/welcome/now" max-age="0"/></p>

This is the simplest of esi tags, and the default max-age is 0, which means do not cache.

Page with ESI Parsing

visit http://localhost:2000 and you'll see:

Date: Mon Aug 06 00:00:00 -0400 2007 which is 62972ns

Caching modules
Edit the index.html.erb and replace with the following:

<p><%= render :esi => "/welcome/now" %></p>
<h2>What time is it again?</h2>
<p><%= render :esi => "/welcome/now"%></p>

If you refresh http://localhost:2000, you'll notice they nanoseconds are different

Lets add a ttl to first call

<p><%= render :esi => "/welcome/now", :ttl => 45.seconds %></p>
<h2>What time is it again?</h2>
<p><%= render :esi => "/welcome/now"%></p>

If you refresh http://localhost:2000, you'll notice they are now the same. Refresh again in the next 45 seconds, and it will not change.

The next tutorial will cover a small TODO application, with inline invalidation and exception handling. Coming Soon!


cameron said...

Pretty interesting for sure. Thanks for posting this stuff.

A couple questions:

1. Is this running in place of regular old mongrel, or in addition to it? (ie. is it additionally proxying to a mongrel that's running simultaneously, or does it have mongrel basically embedded.

2. Is there an instance of something like memcached running, or does the mongrel esi instance store the cached data in itself. (as if it were mongrel _and_ memecached combined)?


Aaron Batalion said...

Good questions.

1) MongrelESI is a separate instance of mongrel that is acting as a local proxy server. It started out as a simple mongrel handler, and grew into its own instance, because we use it to proxy across multiple applications. For the simple use case outlined in this post, thats definitely not needed.

2) Right now MongrelESI caches in memory, but we have plans to add memcache support. We havent added it yet because we dont use MongrelESI in production. We use a commercial cache server that supports ESI and much more.

Just Testing said...

Thanks for the article. How much of a performance hit are you taking for doing the page parsing in mongrel in addition to the parsing that rails does?

todd said...

By parsing I assume you mean HTTP request parsing? A fully cached request will only hit mongrel. For uncached requests I'd have to gather some numbers to say. The mongrel implementation is definitely not ready for prime time. I would say it's ready to be used as a development server. I definitely recommend reading this I'll hopefully get sometime soon to post some more updates.

jney said...

hi Aaron, i know that your tutorial is 6 monthes old now but i'm just trying to implement esi now.
i followed each point of your tutorial, and got "esi:include" tags in my page, but nothing is rendered. I thought you could help me about it

todd said...


I would be very interested in helping you get started with mongrel-esi. Please feel free to post more details about your setup at the new group I setup here =>


Brandon Keene, Senior Software Engineer said...

I'm having the same problem has jney, and I have posted more details to the Google Group.

I am running Rails 2.1 and a manually build version of the gem (version 0.5.4 which seems to be the latest trunk at this time)