Update 28 June 2009: Rollo Tomazzi noted in the comments that the method described below will not work for hash-value attributes. He has written a review of the various methods for setting default attribute values on his blog.
Whilst working with Rails’ ActiveRecord, I was looking for a clean way to insert default data into a model object before it was presented to the controller. In a lot of Rails tutorials I’ve seen, such default data is written in the controller, e.g.:
class PostsController < ActionController def new @post = Post.new(:category_id => 5) ... end end
However, this isn’t very DRY, as I would need to duplicate the initialisation code if I were to create an instance of Post in another controller method. It would make more sense to put such default data into the model itself, so that wherever I create the new Post, it is always initialised with the same default data.
I initially thought the answer would be ActiveRecord's
after_initialize callback method, but this overwrote any attribute values set from the database after a record was loaded.
Instead, thanks to this post, I learned that you simply override the attribute accessor with a value. You can directly access the dynamic attributes set by ActiveRecord using the
class Post < ActiveRecord::Base # Default category ID stored in the Settings hash. def category_id read_attribute(:category_id) or Settings.defaults[:category_id] end # Hard-coded default def title read_attribute(:title) or "New Post" end end