Offbeat Creations company web site now live!

We’ve been building Offbeat Creations for over a year now, and we just managed to find enough time to actually put together a web site for the company!

We’re using the Radiant CMS to run this, to allow us to change the content quickly and easily. I’m still not very comfortable with the way Radiant works, but it does get the job done.

Check us out at Offbeat Creations

(The Offbeat Creations logo was designed by my friend John Betts at Glass Apple)

Posted by Tom Sat, 16 May 2009 18:38:00 GMT


Cool Birthday Gifts from my wife

Lisa got me a few cool t-shirts for my birthday. I think my favorite is the Rock-Paper-Scissors-Lizard-Spock shirt pictured left. This shirt can be got from ThinkGeek , so you too can have the best geek shirt in town!

Posted by Tom Thu, 14 May 2009 19:29:00 GMT


Rails Time Zones and Custom database queries

I’ve been using Rails for so long without caring about how Time Zone’s are processed, that when I recently built a new application with Rails 2.3, I decided that I needed to care about the support for Time Zones since Rails 2.1

Technically, my new app doesn’t really care about time zones, so I could have just left the whole thing alone, but I wanted to see how these worked and get some experience.

The first big surprise is that dates are stored in the database as UTC time. Well, duh! This is usually seamless, but I noticed this detail when my custom code to group by created date on a set of objects suddenly started showing items for tomorrow at about 5pm Pacific time.

Here’s the code I was using:

      Items.find(:all,
                 :select => "DATE(created_at) as created_on, count(*) as c",
                 :group => "DATE(created_at)",
                 :conditions => [ "created_at > ?", 14.days.ago.to_date ],
                 :order => 'created_on desc')

I realized that I needed to adjust for the current Time Zone when retrieving this data.

With some investigation – Google search wasn’t entirely helpful here – I ended up with the following code that retrieves the Time Zone offset in seconds to add to the stored time (for Pacific Time, this is a negative number!)

      zone = 'PDT'
      Items.find(:all,
                 :select => "DATE(date_add(created_at, interval #{Time.zone_offset(zone)} second)) as created_on, count(*) as c",
                 :group => "DATE(date_add(created_at, interval #{Time.zone_offset(zone)} second))",
                 :conditions => [ "created_at > ?", 14.days.ago.to_date ],
                 :order => 'created_on desc')

Now my reported counts by day rollover to the next day at midnight Pacific Time. Adjust your zone setting to suit what results you need.

Posted by Tom Mon, 11 May 2009 06:20:00 GMT


Accessing your database from Rails Metal

I was interested in using the new Rails Metal system for a project I’ve been building. What I want this code to do is take parameters out of the URL and write a record to my database to record these parameters.

This is my first application built with Rails 2.3, and the first application in my company to use Rails Metal in a production environment.

Here’s what I wrote:

  def self.call(env)
      if env["PATH_INFO"] =~ /^\/i\/(\d+)\/(\d+)\/(\d+)\/(\d+)/
        Record.track($1.to_i, $2.to_i, $3.to_i, $4.to_i)
        [ 200, { "Content-Type" => "text/html" }, [ "OK" ] ]
      else
        [ 404, { "Content-Type" => "text/html" }, [ "Not Found" ] ]
      end
  end

This code works great. Runs fast, does what I need.

Until I run it in production under some load!

Suddenly, I see requests backing up and monit is killing my Mongrel’s as the heartbeat call is timing out!

Diagnosing this problem was a bit painful. The RAILS_DEFAULT_LOGGER isn’t available, so I have to create my own logger, and then I used Benchmark.measure to writing out some timings.

The one thing I see is that every 5 calls, a call stalls for exactly 5 seconds. My superfast recording system is taking on average 1 second per request!

The number 5 rings a bell – where did I see that recent;y? I remember now, its in the database.yml file. There’s a new setting for connection pooling. I wonder how that works?

Well, it turns out that Rails Metal really doesn’t set up anything for you, nor does it tear anything down at the end of the request. For Connection Pooling the connection is setup automatically when you access your database, but outside of a Rails Controller, you’d better release this connection before you’re done.

Here’s a simplified version of how I did this:

  def self.call(env)
    if env["PATH_INFO"] =~ /^\/i\/(\d+)\/(\d+)\/(\d+)\/(\d+)/
      begin
        Record.track($1.to_i, $2.to_i, $3.to_i, $4.to_i)
      ensure
        # Release the connections back to the pool
        ActiveRecord::Base.clear_active_connections!
      end
      [ 200, { "Content-Type" => "text/html" }, [ "OK" ] ]
    else
      [ 404, { "Content-Type" => "text/html" }, [ "Not Found" ] ]
    end
  end

Posted by Tom Fri, 08 May 2009 03:34:00 GMT