Pivotal Labs

Alex Chaffee's blog



iPhone-Optimized Webapp

edit Posted by Alex Chaffee on Thursday December 13, 2007 at 03:49PM

Rails 2.0 Released

edit Posted by Alex Chaffee on Thursday December 13, 2007 at 03:44PM

Collapsing Migrations

edit Posted by Alex Chaffee on Wednesday December 12, 2007 at 09:19PM

(6:30 pm: updated to use mysqldump) (12/14/07: updated to remove db:reset since the Rails 2.0 version now does something different.) (12/15/07: updated to not set ENV['RAILS_ENV'] since that gets passed down to child processes)

There was an old hacker who lived in a shoe; she had so many migrations she didn't know what to do. Every time her build ran clean, she spent a whole minute staring at the screen.

Fortunately, she read this blog post and now her db:setup task is so fast she's started building multiple test environments so she can run tests in parallel!

rake query_trace

edit Posted by Alex Chaffee on Saturday November 17, 2007 at 02:51AM

QueryTrace is a great Rails plugin (which I learned about from ErrTheBlog) for pinpointing where in your Rails application that slow query is running. Once you have it installed, your logs won't just tell you that you have a problem, they will pinpoint the exact location of that problem for you. This is invaluable when doing load & performance testing or just trying to understand what the hell ActiveRecord is doing.

Unfortunately, even though it only logs query traces in DEBUG log mode, it still clutters up your test and development logs, and actually slows things down a bit too. So you don't want to leave it in your project's vendor/plugins directory after you're done using it. So I wrote a pair of rake tasks to enable and disable it.

rake query_trace:on                     # Enables the query_trace plugin. Must restart server to take effect.
rake query_trace:off                    # Disables the query_trace plugin. Must restart server to take effect.

The "on" task actually checks out the plugin from query_trace's subversion repository, makes a tarball in vendor/query_cache.tar.gz, then leaves the tarball around so it doesn't have to keep going to the network all the time. You can even check the tarball in to your project and it'll never go to the query_trace repository again. The "off" task just removes the whole vendor/plugins/query_cache directory.

namespace :query_trace do
  desc "Enables the query_trace plugin. Must restart server to take effect."
  task :on => :environment do
    unless File.exist?("#{RAILS_ROOT}/vendor/query_trace.tar.gz")
      Dir.chdir("#{RAILS_ROOT}/vendor") do
        url = "https://terralien.devguard.com/svn/projects/plugins/query_trace"
        puts "Loading query_trace from #{url}..."
        system "svn co #{url} query_trace"
        system "tar zcf query_trace.tar.gz --exclude=.svn query_trace"
        FileUtils.rm_rf("query_trace")
      end
    end
    Dir.chdir("#{RAILS_ROOT}/vendor/plugins") do
      system "tar zxf ../query_trace.tar.gz query_trace"
    end
    puts "QueryTrace plugin enabled. Must restart server to take effect."
  end

  desc "Disables the query_trace plugin. Must restart server to take effect."
  task :off => :environment do
    FileUtils.rm_rf("#{RAILS_ROOT}/vendor/plugins/query_trace")
    puts "QueryTrace plugin disabled. Must restart server to take effect."
  end
end

dot.rake

edit Posted by Alex Chaffee on Monday October 15, 2007 at 12:29PM

[Update: 10/15/07 - incorporated changes by David Vrensk (and a few more from me). Now it merges in associations into the arc, and also deals with inheritance (e.g. STI).]

While googling for articles on Rails associations, I happened upon this gem of a script by Matt Biddulph. I loved it so much I made it a rake task! Once you install GraphViz like this:

sudo port install graphviz

and put dot.rake in your lib/tasks directory, then running this:

rake dot

produces diagrams like this:

BBC Programme Catalogue codebase

And you can also import the DOT source into OmniGraffle for further editing, like this:

open -a "OmniGraffle" model.dot

dot.rake

edit Posted by Alex Chaffee on Saturday September 29, 2007 at 12:06AM

doing it again and again

edit Posted by Alex Chaffee on Wednesday August 08, 2007 at 04:23PM

Here's an RSpec trick I discovered yesterday. Sometimes when you're writing a test you want to loop over some precondition data. But if you do a loop inside your test (or spec), then all the cases will be subsumed in a single test method (or "it" block). This means you'll have the following problems:

  • The first case to fail will cause the rest of the cases not to run. It'd be nice to see them all in a single test run.
  • You won't take advantage of RSpec's cool self-documenting trick of labeling each it block with a full description of the failure, and it'll be harder to debug which case failed.
  • If you're calling into Rails (e.g. in a View spec), you'll only be able to call certain methods -- especially render -- once per test method. That means that you simply can't use a loop inside a method to collapse redundant tests into a single block.

Ruby to the rescue! Instead of looping inside your it block, loop outside your it block.

Lovely Demeter, Meter Maid

edit Posted by Alex Chaffee on Sunday August 05, 2007 at 03:08PM

Wes and Parker pointed us to this article:

Misunderstanding the Law of Demeter by Dan Manges

which is a very nice discussion of the "law" (actually just a suggestion, but a very strong one) that encourages your objects, like small children, not to talk to strangers. Some people seem uneasy with the LoD since it requires them to refactor their objects to have proxy methods all over them. Instead of Paperboy calling customer.wallet.cash you have to put an extra method on Customer -- either cash (attribute delegation -- check out Forwardable in Rails btw) or pay (behavior delegation). But these proxy methods are not clutter, they're the essence of encapsulation. Do not fear encapsulation. Fear is the mind killer.

Anyway, Dan does a great job explaining this concept, until the very end of the article, when he totally chickens out.

Rails Filter Parameter Logging

edit Posted by Alex Chaffee on Wednesday May 30, 2007 at 10:55PM

Q: How do you keep passwords from appearing in plain text in your Rails log file?

A: Filter Parameter Logging

filter_parameter_logging
=> Does nothing, just slows the logging process down

filter_parameter_logging :password
=> replaces the value to all keys matching /password/i with "[FILTERED]"

filter_parameter_logging :foo, "bar"
=> replaces the value to all keys matching /foo|bar/i with "[FILTERED]"

filter_parameter_logging { |k,v| v.reverse! if k =~ /secret/i }
=> reverses the value to all keys matching /secret/i

filter_parameter_logging(:foo, "bar") { |k,v| v.reverse! if k =~ /secret/i }
=> reverses the value to all keys matching /secret/i, and
   replaces the value to all keys matching /foo|bar/i with "[FILTERED]"

(Note that :password matches password_confirm too.)

Rails Conference Links

edit Posted by Alex Chaffee on Monday May 21, 2007 at 08:30PM

(Blabbers who were at the conference, feel free to add your links to this post.)

Other articles: