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?