Taking expirations out of caching

It’s been said that the two last hard problems in programming are naming things and expiring caches. The first is going to be hard to sidestep entirely, but what if we could the second? Tobi arrived at a eureka moment for just that using Memcached and various kinds of caching. Instead of manually expiring things, just ask for a specific version, and let the caching engine take care of dumping that which isn’t used any more.

Read more on The Secret to Memcached.

Javascriptian REST

Eric Mill went ahead and created Jester, a library that lets you manipulate your Rails-style resources with javascript models. I think it’s great that we’re seeing implementations in other languages. This python port of Routes implements map.resources, can a python port of ActiveResource be far behind?

How to get more literal URLs and still use IDs

Obie walks through the technique for getting more search engine-friendly URLs and still retain the ease of use with auto-incrementing ids.

It’s the same technique we used on the new 37signals blog engine to get urls like http://www.37signals.com/svn/posts/247-calling-all-basecamp-customers-in-nyc-or-chicago.

The 247 is what Rails see and calling-all-basecamp-customers-in-nyc-or-chicago is what Google will focus on. Have your cake and eat it too!

Using custom mime types

So, you’ve started using Rails’ new mime type support with responds_to, but you were wondering how to add your own custom types? Luckily, Geoffrey Grosenbach (aka topfunky) is there to show you the way. His example involves registering an extension for .png, and generating a custom icon for an order in his shopping cart with some RMagick-fu. His example looks something like this:

Mime::Type.register "image/png", :png

# then in your controller action
def show
  respond_to do |format|
    format.html { }
    format.png { }
  end
end

Mime::Type.register will add the image/png mime type to the collection of mime types, bind it to the .png extension. It also creates a special Mime::Type instance at Mime::PNG. Check out the great post and the comments for more tips on caching and RMagick.

Note: After some investigation, I’ve found that using Geoff’s :format hack is not required on Rails 1.2 if you make the request with the :format parameter. Using routes like formatted_post_path(@post, :xml) will give you a path like “/posts/1.xml”. Accessing that will write public/posts/1.xml, regardless of what the page_cache_extension is.

The Rails Way on premature extraction

Koz and Jamis has posted their first article on The Rails Way covering premature extraction. It’s a great way to start off the show of Rails learnings. Since it’s so easy to abstract and extract in Ruby, it’s ever so tempting to begin doing so before you have more than one instance to triangulate the best approach with.

Capistrano cheat sheet

David Pettifer has created a compact Capistrano cheat sheet in PDF format. It summarizes helper methods, pre-defined variables, standard tasks, capfile syntax, standard release directory structure, and more. So go ahead, download it!

(For those arriving late to the party, Capistrano is a utility for executing commands in parallel on multiple remote hosts. You can read all about it in the Capistrano manual.)

Unobtrusive Javascript Plugin

Dan Webb and Luke Redpath have release the latest version of their Unobtrusive Javascript Plugin for Rails. It solves several of the main problems people run into when working with unobtrusive javascript:

  • Development isn’t as intuitive with Rails when you’re defining your custom javascript behaviors in an external file.
  • When working with pages with lots of images and content, the behaviors won’t be enabled until everything is downloaded and window.onload is called. It’s been solved with some nasty cross-browser javascript hacks, all handled transparently by Dan’s LowPro extension for prototype. This has been a big deal for me personally, so it’s nice to see it all solved.

UJS attempts to solve this by taking defined behaviors in the view and creating a tailored javascript file for it. Smart conditional GET and page caching techniques can be used to save bandwidth and time.

All in all, it looks like Dan and Luke did an excellent job on the plugin. Anyone using it? How’s it working out for everyone?

Pound makes lighty and Mongrel play nice

With the rocket rise of Mongrel, we’ve seen a growing number of folks jump ship from lighttpd to Apache 2.2 because of mod_proxy_balancer. It’s great to see that Mongrel is putting Apache back on the map as a premiere Rails web server, but unless you desire Apache for other reasons, you certainly don’t have to jump ship.

The trouble with lighttpd is the state of its mod_proxy implementation, which leaves a lot to be desired when used as a balancer between multiple Mongrel backends. But because the whole Rails deployment stack is going straight HTTP, it’s surprisingly easy to rectify. All you need is to add a more capable load balancer to the mix and you’re golden.

One such balancer that has seen a lot of play lately is Pound (OS X install notes). It’s light, fast, and proven on mega sites. So here’s what you do if want to stay with lighttpd and still use Mongrel:

  • Setup lighttpd on port 80 with mod_proxy to point at one back-end server (see the Mongrel lighty docs, but just only use one backend instead of four).
  • Setup Pound on a high port, like 7999, and make it point to any number of Mongrel processes (see the Mongrel Pound docs).
  • Start n number of Mongrels, from say port 8000 through 8002, using either mongrel_cluster or the soon-to-be-committed Mongrel-compatible script/process/spawner

And bingo, you should now have a production-ready stack ready to take on the world. This is a pretty good outline of how we at 37signals intend to use Mongrel in production shortly.

You can also take pleasure in the fact that Jan Knesche is busy at work making the Pound crutch unnecessary. Over the Summer, he has promised to elevate mod_proxy to be on par with the competition, and this three-way stack should again become a two-way one.

Tips on how to improve application efficiency

Rails performance specialist Stefan Kaes, who writes extensively about optimizing Rails over at Rails Express has a lengthy article at the new InfoQ site called A Look at Common Performance Problems in Rails.

Kaes identifies various development practices that will slow down your Rails applications, such as repeating computations that only need to be run once and then cached. If you’ve located some slowness in your application, Kaes may have already identified some of the likely culprits.

A gentle reminder about pluralizations

Watching the RSS feed from the Ruby on Rails trac is a great way to keep up on what's happening in Rails development. If you're doing any development on the Ruby on Rails project it's required reading. Even if you just are using Rails for a web app, it's useful to keep up on what bugs people are reporting.

Lately I've noticed a slew of bugs being opened against the Inflector, the class in Rails that transforms words from one form to another: singular to plural, classname to tablename, etc. The bugs all complain that Inflector is getting a pluralization or singularization wrong. But this isn't a bug in Inflector, it is just an inherent limitation of how it works. But fear not, there is a better solution than opening a bug against the Inflector.

I guess this has been a constant thing over the history of Rails, but since it's still going on, it deserves a rehash.

New in Rails: Module#alias_method_chain

Though not an outward facing feature, changeset 4276 introduces a nice method to DRY up and encapsulate the common pattern of aliasing a method so that you can build behavior on top of it.

All over the internals of Rails you’ll find code like this in a module:


  module Layout #:nodoc:
    def self.included(base)
      base.extend(ClassMethods)
      base.class_eval do
        alias_method :render_with_no_layout, :render
        alias_method :render, :render_with_a_layout

  1. … etc

This makes it so that when the module is included into the base class, it adds behavior onto some method in that class without the method having to be aware of the fact that it’s being enhanced. In this case, the render method of ActionController::Base is enhanced to wrap its output in a layout.

The new Module#alias_method_chain wraps up this pattern into a single method call. The above example, once refactored to use Module#alias_method_chain, would simply be:


alias_method_chain :render, :layout

This will be used to refactor quite a bit of Rails internals which may not be of immediate relevance to what you do, but it serves as a nice example of the mechanisms Ruby provides for software organization. Small victories.

Use params, not @params

I still frequently see people in the #rubyonrails channel using @params in their code. For a while now @params has been deprecated in favor of simply params. For those who just skim these blog posts:

Use params, not @params

Why? When you use the params method, it allows for the implementation details of the parameter hash to be changed without breaking existing code. If the implementation of params changed you wouldn’t have to change your code at all because the single point of access for the parameters would just remain the params method. So, the details of what is happening behind the scenes don’t matter. If, though, you use the @params instance variable directly, you’ve broken encapsulation and consequently the ability for the implementation to be easily modified. Methods can be refactored, but instance variables can’t. Today the params method just wraps the @params instance variable, so still using @params works, but that’s not guaranteed to always remain the case.

Same goes for request, response, session, headers, template, cookies and flash.

Basically, a good rule of thumb here is don’t use an instance variable in your controller or view unless you created that instance variable.

Even the old @content_for_layout in the layout is deprecated in favor of just using yield in its place. Also content_for('some_fragment') is now accessed with yield :some_fragment rather than @content_for_some_fragment.

Writing Domain Specific Languages

If you’ve been in the Ruby community for any time, you will likely have heard about “Domain Specific Languages”. Rails uses the concept extensively with its macro style methods for setting up associations, callbacks and validations in models, as well as layouts and filters in controllers. Indeed, Ruby provides great support for creating your own DSLs. It may have become easier to spot domain specific languages, but how does one actually implement them?

Rails core team member Jamis Buck has taken the time to guide you toward understanding the fundamental mechanisms used to create domain specific languages. Get up to speed with his tutorial, Writing Domain Specific Languages, and you’ll be creating elegant abstractions sooner rather than later. What a treat.

Stress testing your protected pages

David came up with a quick tip for anyone stress testing protected pages with a stateless tester, such as siege.

  1. Log in with your browser
  2. View the cookies and find the session id (Firefox has a handy cookie search tool)
  3. Prepend the queries with ?_session_id=YOURSESSIONID

Now, any requests made will be as though they came from your account.

Do you have any other handy tips for stress testing your Rails applications?

Fast Rake Task Completion for Zsh

Those of you who love running Rake tasks but don’t like typing are in for a treat. Although there’s been task completion for Rake for a while now, most of the scripts for it are painfully slow, especially with Rails’ Rakefile.

Below is a small zsh completion script that uses a cache file (named .rake_tasks) to improve the performance of your tab keystrokes.

To use, throw it in your home folder somewhere and add source $HOME/.rake_completion.zsh to your .zshrc file.

A few disclaimers: Yes, it doesn’t work with lowercase named rakefile‘s. Only barbarians use such names though, so hopefully you won’t have a problem there. And no, it doesn’t complete the other assorted arguments that the rake command can accept, frankly because I rarely use them.

Without further ado, here’s the bytes.

_rake_does_task_list_need_generating () {
  if [ ! -f .rake_tasks ]; then return 0;
  else
    accurate=$(stat -f%m .rake_tasks)
    changed=$(stat -f%m Rakefile)
    return $(expr $accurate '>=' $changed)
  fi
}

_rake () {
  if [ -f Rakefile ]; then
    if _rake_does_task_list_need_generating; then
      echo "\nGenerating .rake_tasks..." > /dev/stderr
      rake --silent --tasks | cut -d " " -f 2 > .rake_tasks
    fi
    compadd `cat .rake_tasks`
  fi
}

compdef _rake rake

(Use at your own risk. Comments and improvements welcome.)

Annotated models

Ever working with a model and you forget what all of its columns are? Ever find yourself with your schema.rb open in a separate window so you can see what the structure is of your tables?

Dave Thomas, of Rails Pragmatic Studio fame (among a brazillion other things), hacked up a plugin that adds a comment block to the top of all of your model classes documenting the current schema for the given model. It ends up looking something like this:

  1. Schema as of Sun Feb 26 21:58:32 CST 2006 (schema version 7)
    #
  2. id :integer(11) not null
  3. quantity :integer(11)
  4. product_id :integer(11)
  5. unit_price :float
  6. order_id :integer(11)
    #
class LineItem < ActiveRecord::Base belongs_to :product

When the schema is updated, the comment is updated to reflect the new schema.

Install it with the plugin script:

script/plugin install http://svn.pragprog.com/Public/plugins/annotate_models

Run it with a custom rake task:


rake annotate_models

Check out the caveats in the README.

Thanks for sharing Dave.

New in Rails: Enumerable#group_by and Array#in_groups_of

Changeset 3726 adds two little methods to ActiveSupport: Enumerable#group_by and @ Array#in_groups_of@.

Enumerable#group_by is for collecting an enumerable into sets, grouped by the result of a block. Useful, for example, for grouping records by date.


     latest_transcripts.group_by(&:day).each do |day, transcripts| 
       p "#{day} -> #{transcripts.map(&:class) * ', '}"
     end
     "2006-03-01 -> Transcript"
     "2006-02-28 -> Transcript"
     "2006-02-27 -> Transcript, Transcript"
     "2006-02-26 -> Transcript, Transcript"

Enumerable#group_by will be baked right into Ruby in the future, and currently lives in the 1.9 branch.

Array#in_groups_of let’s you iterate over an array in groups of a certain size, optionally padding any remaining
slots with a specified value (nil by default).


     %w(1 2 3 4 5 6 7).in_groups_of(3) {|g| p g}
     ["1", "2", "3"]
     ["4", "5", "6"]
     ["7", nil, nil]

You gotta love the elegant encapsulation afforded by blocks! Yield.

New for Rails 1.1: Integration Tests

If you’ve ever tried to properly test complex scenarios involving multiple controller actions, you will notice that the Rails Functional Tests fall flat. The new Integration Tests, which have just been introduced into the Rails trunk, will solve that. From the documentation:

An IntegrationTest is one that spans multiple controllers and actions, tying them all together to ensure they work together as expected. It tests more completely than either unit or functional tests do, exercising the entire stack, from the dispatcher to the database.

The provided example also shows a glimpse into the testing DSL that is used in Campfire:

class AdvancedTest < ActionController::IntegrationTest
  fixtures :people, :rooms

  def test_login_and_speak
    jamis, david = login(:jamis), login(:david)
    room = rooms(:office)

    jamis.enter(room)
    jamis.speak(room, "anybody home?")

    david.enter(room)
    david.speak(room, "hello!")
  end
end

Integration Tests will be included with Rails 1.1. Get ready!

SwitchTower with Perforce

Richard McMahon has written about using Perforce as the SCM with SwitchTower (here). He’s even written a custom Perforce SCM module for SwitchTower, so if you’re a Perforce user wanting to dabble with SwitchTower, it looks like you’re in luck.

(Richard has given his permission for the Perforce SCM module to be included with the next SwitchTower release.)

Freezing your Rails when you deploy shared

If you’re running a Ruby on Rails application on a shared host, it’s super-double-plus recommended to freeze your Rails. Freezing your Rails means putting the framework into vendor/rails instead of floating with whatever gems that are installed on the host. Because if you do so, you’ll automatically be upgraded when they are. Not a great thing for a production application to have forced upon itself.

The great news is that this is silly simple. If you’re running 0.14.x or newer, you can simple do rake freeze_gems, and the current gems the system is used are unpacked into vendor/rails. Now the host can update as silly as it wants without affecting your application.

SwitchTower problems on OSX

This has been coming up often enough that it deserves to be posted somewhere visible. If you are trying to use SwitchTower with the stock version of Ruby that ships with OSX, you will fail. The stock OSX version of Ruby has a bad OpenSSL module, which wreaks all kinds of havoc with SwitchTower.

The solution is to install a non-stock version of Ruby, either via DarwinPorts, or Fink, or even just the good-old manual “configure/make/make install” process.

Get 10-15% more performance with MySQL/Rails

Rails 0.14.x and forward contains a hefty performance increase for the MySQL adapter, but it requires that you have the latest version of the underlying, native bindings (2.7). On Stephan Kaes’ benchmark suite, the upgrade is 10-15%:

You can get the latest MySQL bindings with gem install mysql (or gem install mysql -- --include=/usr/local/lib on OS X). The additional speed upgrade will automatically kick in as soon as you have the latest bindings (to check, open the console, require ‘mysql’, puts Mysql::VERSION, and expect to see 20700).

UPDATE: If you’re on Windows, Justin Rudd went through the trouble of describing how to make it work there.

Themes, migrations, graphs, and alternate routes

A bunch of good articles on various Rails-related topics lately:

What's with this DoubleRenderError?

Another haunting feature of 0.13 is the DoubleRenderError. Jamis explains it purpose:

In order to understand why the DoubleRenderError was necessary, you need to understand something about the render and redirect_to methods that may surprise you. Many programmers expect a call to render or redirect_to to immediately cease execution of their action and return the result back to the browser. This is not the case in Rails. Unless you explicitly return after rendering or redirecting, your action will continue on its merry way as if nothing had happened.

Go read the full thing and you’ll go “ahhhh, thank heavens for DoubleRenderError!”.

Watch for huge requests on default FCGI

As you might have noticed, 43things have been down for the count a few times since launch with nasty 500’s. The cause was the combination of default FCGI settings and a bad-ass RSS query that pulled out everything from the system at once and took up a couple of pages in the log.

That action couldn’t be rendered within the 30 second limit that FCGI imposes by default, so Apache suspended the connection to FCGI and caused hits to that particular FCGI process to go out of commission.

Lessons learned…

  1. Make sure you don’t have any actions that take longer than the timeout limit in FCGI
  2. Increase the default timeout limit if you have actions that you expect to take close to 30 seconds or more