Tuesday, February 01, 2011

Setting non-nullable form field defaults in Rails

Recently, I found myself following a pattern for setting non-nullable form field defaults in a Rails model.

Basically, instead of relying on the database schema:
  create_table "user_queries", :force => true do |t|
    ...
    t.string   "sort_field", :default => "username", :nil => false
  end


I add an after_initialize hook to the ActiveRecord model:
  after_initialize :set_defaults

  def set_defaults
    self.sort_field = "username" if sort_field.nil?
  end


The reason I do that is because of an issue I ran into when specifying the non-nullable default in the database schema. When the default value requirement changes (e.g. change default from "username" to "last_name"), I end up having to create a migration that modifies the column when using a database that supports column modification (e.g. MySQL), or worse yet for databases that do not support column modification (e.g. PostgreSQL), I create a migration that adds a new column, migrates older's column data to new column, and removes older column.

By having the non-nullable default specified in ActiveRecord models instead, change becomes as easy as updating the model's test and the default value specified in the code.

Of course, the disadvantage to this approach is it does not ensure that the default value is set when interacting with the database without ActiveRecord. But, it works if that is not a requirement in your client environment.

Would be curious to know if others ran into the same problem and whether they addressed it in the same way.

1 comment:

Matt Polito said...

Very cool idea/implementation. I've used this gem to do something similar with good results as well:

https://github.com/FooBarWidget/default_value_for