page caching your whole app
Courtenay : December 16th, 2005
The problem: we had to launch a site on a box with limited resources -- we were expecting at least a few 100k hits/day, and weren't confident of rails' ability to scale.
So here's what we did: we turned on page caching (humorously referred to as "paching") for everything.. however.. the page had a box which contained a login/password form, which changed to "logged in as ... you can (edit profile :: edit articles :: blah blah)" when they logged in.
So, how to maintain this dynamicity without sacrificing the page caching? There are many ways to do this; I'll be showing you the page rewriting method; but technoweenie will be presenting his awesome ajax-and-behavior technique.
update[1]: thanks to technoweenie for some additional examples and code.
update[2]: you can now view a live-action demo here
Based on my previous experience here (I had developed the original "posted x minutes ago" in JS for typo) here's how we solved it:
h2. 1. strip da erb
first, remove all user-referencing erb code from the views.
h2. 2. rewrite the login-module box
.. so it shows both the login form, and the user-info form like this:
h2. 3. create the js action
note: this can be done with RJS, but it's not in 1.0, so I'm leaving this in raw JS for now..
Note that this action isn't cached; however; with a bit of extra work this could be done..
var User = {
activate: function() {
$('username').innerHTML = User.name;
Element.hide('unauthorized');
Element.show('authorized');
},
name: "<%= @current_user.name %>"
}
then you can additionally create an array of <LI> containing the user actions (depending on role), and you dynamically insert those too, into the user__tasks UL
include this action with
in the header
if you want to page cache the JS file, too, you can do something like:
Remember the .js extension so that your web server serves it with the proper content type. Here's a sample action:
def profile
headers['Content-Type'] = 'text/javascript'
sess_id = params[:session_id] =~ /^(\w+)\.js$/ ? $1 : params[:session_id]
if not logged_in? or sess_id != session.session_id
render :text => ''
end
end
Now, I'm going to wind back time a little to step 2.
h2. 4. go back in time
after you've closed all the <divs>, insert
Note that this doesn't wait for page onload; it runs immediately, so you have to make sure you're not in a <table>block (or it'll error in IE). This also means the page appears accurate with no delay.
In theory, you could even decouple this view from any controller action; just store the username and some permissions-triggering code in cookies, and do all the work with JS. however, we found that a simple controller-based JS action easily sustains about 40 req/second, which is 144k hits/hour, and plenty enough for us.
Sorry, comments are closed for this article.