Have you ever wished you could mix Rack or Sinatra into your Ruby on Rails application just to get its raw throughput on certain parts of your application?

Let’s face it, sometimes, the Rails framework is overkill when we’re returning a simple string or an object in JSON as our response. Your answer for these instances is here. Rails Metal.

Performance

Some people have reported huge speed increases in Rails Metal over the Rails MVC framework. This article claimed a 25x increase over Rails. Pratik Naik from the Rails Core team benchmarked a more believable increase of 4x. Whatever the case, the performance advantage is worth noting.

Ruby on Rails on Rack?

Rails Metal is effectively a mechanism for running your code on Rack, which is the new underpinning for Ruby on Rails—replacing the Ruby CGI library. The Rack code you write into Rails Metal is run as middleware on your application. In other words, each Rails Metal is effectively an application that intercepts the requests to your Ruby on Rails application and either responds to the request, or passes control up to the next piece of middleware in the stack until it reaches your Ruby on Rails application.

Rails Metal Responses

To send a response back to the user, we use the Rack response notation. Here’s a quick example:

1
[200, {}, "This is response text."]

This notation has 3 parts. The first is a number representing the status of the response. Here’s a quick list of common response statuses.

  • 302 – Redirect
  • 200 – Success
  • 404 – Pass control to the next application in the stack.

You can see that a 404 sends control to the next Rails Metal in the stack—unless there are no more, then it sends the request and control to your Ruby on Rails application. If anything else is returned, the rest of the applications in the stack do not get executed.

The second part of the response is the header. Here are some common keys for the hash used to form the HTTP response header.

  • Content-type – This is mime type of response data. You may see “image/jpeg” or “image/png” for images being returned.
  • Location – You use this to specify the location you’re redirecting to when you send a 301 or 302 status

The last part of the response is the response body. This is the HTML content for returning a webpage. It can also be the data for an image or stylesheet—just remember that you must specify the content-type in the header.

Here are a couple of example responses:

HTML response:

1
[200, {"Content-Type" => "text/html"}, "<html><body style=\"color: red;\">Hello, World!</body></html>"]

Redirect response:

1
[302, {"Content-Type" => "text/html", "Location" => "http://www.google.com"}, "You will be redirected to Google"]

Image response:

1
[200, {"Content-Type" => "image/png"}, @image.raw_data]

Rails Magic in Metal

Your Rails Metal application has ActiveRecord available to it. This means that you can access your data in the normal Rails fashion when working in Rails Metal.

Here’s a simple example of recording a request to a download link and then redirecting to the actual download site:

1
2
3
4
5
6
7
8
9
10
11
12
13
# Allow the metal piece to run in isolation
require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails)
 
class Downloads
  def self.call(env)
    if env["PATH_INFO"] =~ /^\/download/
      download = Download.find_by_id(env["PATH_INFO"].split("/")[2].to_i)
      [302, {"Content-Type" => "text/html", "Location" =&gt; download.location}, ["You are being redirected."]]
    else
      [404, {"Content-Type" => "text/html"}, ["Not Found."]]
    end
  end
end

You can see in the above example that it uses an ActiveRecord object—Download—to get the location for the redirect.

Adding Metal

Adding a Metal app to your Ruby on Rails application is as easy as running the built in generator.

script/generate metal downloads

Final Thoughts

Overall, I’ve found Rails Metal to provide nice increases in throughput on my applications as well as an easy way to separate certain functionality in to its own application. I’ve also found that if I need highly dynamic content in my response similar to what is provided by a view with erb tags I’m better off putting that functionality into a Ruby on Rails application.

If you need to change the order your Rails Metal middleware stack, check out Get Your Rails Metal in Order.

All in all, I’ve found Rails Metal to be a useful tool in my arsenal for scaling my Ruby on Rails applications.

Update

If you’re looking for examples or ideas, I’ve added 9 Ways to Use Rails Metal which is a list of 9 Metal applications I’ll be coding up over the coming weeks.

  • DZone
  • Twitter
  • Slashdot
  • Delicious
  • Digg
  • Technorati Favorites
  • Facebook
  • Reddit
  • StumbleUpon
  • LiveJournal
  • Squidoo
  • Google Bookmarks
  • LinkedIn
  • Share/Bookmark

4 Comments »

9 Ways to Use Rails Metal

June 13, 2009

[...] 'http://charlesmaxwood.com/9-ways-to-use-rails-metal/';tweetmeme_source = 'charlesmwood'; I wrote a quick overview of Rails Metal earlier and started thinking that it would be nice to provide some examples of how you could use it [...]

GarykPatton

June 15, 2009

Hi. I like the way you write. Will you post some more articles?

Chuck

June 15, 2009

I’m planning on it. I’ve really enjoyed researching as well as putting the content together. Are there any topics you’re interested in learning about?

Zoran

June 20, 2009

charlesmaxwood.com to GoogleReader!
Thanks
Zoran

Leave a comment