I've put some thought into this and have done some experimenting and
thought I would bring up a few points of discussion:
It seems to me there are multiple definitions of a "default value."
1. Database/Model level defaults:
In relation to a model object it would be values that would define the
"natural state" of an attribute. Take for example an attribute
access_level on a User object. A natural default state may be a value
representing a "regular" user (say 1 = "Regular user").
This type of default value can be provided right in your database
migration like:
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.column :created_at, :datetime #<< Notice that Rails will
automatically take care of the default value
t.column :first_name, :string
t.column :last_name, :string
t.column :access_level, :integer, :default => 1 #<< 1 = Regular
user
end
end
def self.down
drop_table :users
end
end
It is also possible (although it seems unnecessary given the above) to
set these types of defaults in the model class like:
class User < ActiveRecord::Base
def initialize(params = nil)
super
self.access_level ||= 1
end
end
In other cases the "default value" may actually be related more to a
particular view.
I recently ran into an example like this: I had a event scheduler
that I wanted a default value for the current time to be set on the
datatime selection control. In my opinion this is not a model level
default value. To create an event, expecting people to subscribe to
the event later, it is not the "natural state" of the Event object to
have a start_time = Time.now. However, it is convenient to initialize
the form's control to default to the current date and time to make the
user's selection process easier.
It just happens that the built-in time widgets do this (I think so
anyway). But in any case the initial state of the model object's
start_time attribute to be nil and not Time.now.
So assuming that this behavior is not built into the form's control
object Rails provides a convenient way to construct a new object with
some attributes initialized that can be set from with the controller
like:
# GET /people/new
def new
@person = User.new(access_level => 1)
end
Maybe some purist MVC guys would say that is breaking the MVC design
pattern, and maybe it is, but sometimes the convenience is so great
that it's worth bending the rules a bit. However, this is similar to
many "factory constructor" design patterns that I often see in use.
It would be more "pure" if the form's control were extended to provide
a default option.
Something like:
<p>
<b>Access Level</b><br />
<%= f.text_field :access_level, :options => {:default => 1 }%> #
DON'T do this it's just made up to illustrate a point
</p>