Piotr Sarnacki home

Lightweight controllers with rails 3

Some time ago I showed you, how easily you can reuse rails 3 modules. Today I want to present lightweight controllers, which is also really really easy in rails 3.

Why would you want controller to be more lightweight? Speed of course. We all know that rails can’t scale and ruby is slow, let’s make it a little bit faster ;)

Let’s start with getting familiar with new controller architecture. The base for all the controllers in rails is AbstractController::Base. If you want to build controllers without support for handling requests, you can start with that as a base. What if we want to create something looking more like standard rails controllers? We can check how does implementation of ActionController::Base look like: ActionController::Base

As you can see, it inherits from ActionController::Metal and includes bunch of modules. Looks like Metal will be a good start for our purpose. Let’s say that we want to render a simple JSON response generated from a model:

# app/controllers/api_controller.rb
class ApiController < ActionController::Metal
  include ActionController::Rendering

  def index
    render :text => "Good morning!"
  end
end

As you can see I created controller that inherits from ActionController::Metal and included ActionController::Rendering. To render simple JSON response, we will not need anything more.

How fast is it comparing to ActionController::Base? For comparison I’ve created controller with exactly the same action:

# app/controllers/home_controller.rb
class HomeController < ActionController::Base
  def index
    render :text => "Good morning!"
  end
end
I’ve done a few benchmarks, but don’t take it too seriously, these are not scientific, I just wanted to show you how approximately can it differ. Here are ab results: https://gist.github.com/738168. As you can see, ActionController::Metal is almost 40% faster. This can of course vary, depending on version of ruby, concurrency (I used 1) and other factors, but clearly it can give you nice boost.

Of course trained eye can easily spot an issue here. Do you think that someone will actually return a response like that? Hardcoded string?Srsly? I guess not. But there certainly are situations, when you can profit from using that kind of controllers. If all you need to do, is to return text response, that most of the time is fetched from cache and is hit frequently, this should work pretty well. Some of you may also ask, why can’t we use Rails Metal, which is available for quite some time now rack middleware (rails metal was removed in rails 3). We could, but then we loose possibility to use router and include other modules to ActionController::Metal (like ActionController::Helpers or other useful things).

I hope that this post will help you to experiment with new Rails 3 cool features! If you want more of that stuff, in better form and with much better explanation and depth, I highly recommend reading José Valim’s book Crafting Rails Applications!


If you liked this post consider following me on twitter.
blog comments powered by Disqus
Fork me on GitHub