Creating default attributes for ActiveRecord objects without using migrations

Sometimes we want to set a default attribute value on new ActiveRecord objects but we find that we can’t set that value in the migration. For example, defaults must sometimes be determined by executing code.

I ran into this recently on RubyRags. We wanted to set every new Product to have a certain product_type_id by default. We know we wanted it to be the type with the name of “tshirt,” but since the database assigns id’s willy-nilly for us, we should really just look at that assignment process as a randomized black box rather than depending on IDs to be generated in a predictable way. So we can’t just assume it’s going to be “1” and set it in the migration, even though that’s probably going to be true:

# retarded!
class CreateProducts < ActiveRecord::Migration
  def self.up
    create_table :products do |t|
      t.integer :product_type_id, :default => 1
    end
  end
end

Instead, we came up with a solution that is perfectly dynamic and simple to implement.

You just override the initialize method.

def initialize(attributes=nil)
  super(attributes)
  self.product_type = ProductType.find_by_name('shirt')
end

You need to pass the attributes along in case you’re going to do something like

Product.create( :name=>whatever )

and you need to call super so that all the stuff magic in ActiveRecord::Base still happens. But still, that’s pretty easy enough, no?