So I’m working on a Rails application with a MS SQL Server 2005 back-end. The application needs to access the Dynamics GP data stored on that server, and while I could have other tables (users, sessions, etc) stored separately in, say MySQL, I elected to keep them all together, at least for the time being. (I’ll detail the steps I used to get unixODBC and FreeTDS installed and working on OpenBSD 4.2 in another post. In the meantime, this is the Rails wiki article that got me started.

Anyways, back to the problem I ran into. Parts of the application follow the standard Rails new/create idiom. A user clicks on the New Foobar link, and gets taken to a blank form to fill-out. However, with this unixODBC/FreeTDS/MS SQL setup, all of my text fields were winding defaulting not to blanks, but to the text string “NULL”.

A quick search on Google turned up this issue on Rails Trac, along with a temporary monkeypatch fix posted in the comments by meekish:

ActiveRecord::Base.class_eval do
  def attributes_from_column_definition_with_null_fix
    returning attributes = attributes_from_column_definition_without_null_fix do
      attributes.each_value { |value| value.replace('') if value == 'NULL' }
    end
  end

  alias_method_chain :attributes_from_column_definition, :null_fix
end

He suggested putting this in a lib/ file, and requiring that file in environment.rb.

This was cool, and it almost met my needs. Being picky, I wasn’t quite satisfied with replacing a “NULL” string with a blank. It’s supposed to represent a null value. Then there’s a more practical issue: if new action created a new object, saved it, and immediately redirected to an edit action (long story), Ruby would scream.

So here’s my version of this monkeypatch that instead replaces “NULL” strings with nils:

ActiveRecord::Base.class_eval do
  def attributes_from_column_definition_with_null_fix
    returning attributes = attributes_from_column_definition_without_null_fix do
      attributes.each_pair do |key, value| 
        attributes[key] = nil if value == 'NULL'
      end
    end
  end

  alias_method_chain :attributes_from_column_definition, :null_fix
end

Works like a charm.