Natural Language Date & Time Parsing for ActiveRecord (Rails 2.1+)

If you read my previous post on natural language date & time parsing for ActiveRecord and tried it on Rails 2.1 or later, you may have noticed it works fine for dates, but not dates with times.

As part of the time zones feature introduced in Rails 2.1, changes were made to how ActiveRecord parses date/time columns during attribute assignment. The overridden method I showed in my previous post is never called, and Chronic doesn’t get a chance to parse the string.

For Rails 2.1 and later, instead you need to provide a new version of ActiveSupport::TimeZone#parse:

class ActiveSupport::TimeZone
  def parse_with_chronic(string)
    time = parse_without_chronic(string)
    if time.nil?
      time = Chronic.parse(string, :now => self.now)
      time = self.local(time.year, time.month, time.day, time.hour, time.min, time.sec)
    end
 
    time
  end
 
  alias_method_chain :parse, :chronic
end
Rails 2.2 Integration Tests Always Use the Cookie Store

If you’re upgrading an existing Rails app to 2.2 or later, and you aren’t already using the cookie session store, you will likely find that your integration tests are failing. The symptom will be a “500 Internal Server Error” mixed in with “E”s for each failing test. The stack trace at the end will start with:

NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]=
.../vendor/rails/actionpack/lib/action_controller/integration.rb:294:in `process'

If you dig into integration.rb, you’ll find it’s trying to access the @header hash.

The cause of this problem is that integration tests are now hard-coded to use the cookie session store. If you aren’t using it, there’s a good chance you haven’t defined a secret for it in your environment.rb. To solve, add this to your environment.rb:

  config.action_controller.session = { :session_key => '_session_key',
    :secret => 'long unguessable string' }

Get your own “long unguessable string” by running rake secret.

Code the Phone

I’ve started a new blog, Code the Phone, with a friend of mine. The purpose of it is all things related to application development and the business of selling apps on smartphones. Not surprisingly, we aren’t talking about anything other than the iPhone at the moment.

Subversion vs. Git

If you don’t like making up your own mind and prefer to ride the wave of whatever happens to be popular right now, you might think that, when it comes to source control, there are two choices: Subversion and Git, and no middle ground.

(Yes, there are others, but I’m trying to keep this simple.)

This is just not true. Daniel Jalkut addresses this from one perspective in Zealotry For Good And Evil, but I’d like to add to his arguments from the perspective of a single developer or small team.

Subversion works in mostly the same way that source control has worked for decades, so for anyone that’s been in the industry for a while, there are few surprises. This means that, for the most part, the source control system stays out of the way and does the jobs we need it to.

Git was built to solve a different problem: how to provide source control to a globally distributed team, where one centralized, master repository was viewed as a bug, not a feature. Individuals or small teams don’t have this problem.

Fundamentally, though, rather than having arguments about which source control system is “better,” recognize that they are tools, with different strengths, and use the one that feels the best to you and lets you get your work done efficiently.

Personally, I’m experimenting with using Git as a means to version controlling projects for clients where I expect to make changes in many places, but I don’t expect the project to last very long. For these, it seems more trouble than it’s worth to carve out a place in my central Subversion repository, especially because I won’t need to provide outside access to it. Git’s placement of the repository within my working tree is a feature here.