Rails: Setting Default Attributes on an ActiveRecord Model
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 read_attribute and write_attribute methods:
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