This may be obvious but as it took me a little while to figure it out, I thought I’d share it with you.
If you want you have default values, the easiest way is to set your defaults within the table. But often, that is too late. In your new action, you want the defaults to appear within the form (or whatever). So instead, you have to set the defaults in the constructor - but in such a way that won’t interfere with Active Record’s standard behaviour.
In particular, there are several ways of instantiating an object:
thingy = Thingy.new
This creates a brand new thingy, with blank values (for example, in a new action).
thingy = Thingy.new params[:thingy]
This creates a brand new thingy, with values taken from the supplied parameters (for example, in a create action).
thingy = Thingy.find params[:id]
This creates a brand new thingy, loaded with values taken from the database.
Internally, ActiveRecord::Base’s constructor takes a hash as a parameter - with a default value of nil. So if you want to override it, you have to honour its original semantics, otherwise the rest of the framework will complain.
So, imagine the Thingy model has attributes “name” and “price” that you want to initialise:
def initialise(params = nil) super self.name = "default" self.price = 1.50end
This won’t work - because the second and third instantiations will have their values overridden. Instead, what you need to do is this:
def initialise(params = nil) super self.name = "default" unless self.name self.price = 1.50 unless self.priceend
You could use
self.name ||= "default"
but I had one weird situation where it didn’t work (unexplained) and I also find it more readable.
Thanks!
Though I have to say it’s the American spelling of initialise they use. So it’s “initialize”.
By any chance was your unexplained one a boolean that you were defaulting to false?
The initialise/initialize always gets me!!
And I can’t remember what the issue was but if it was then ||= false wouldn’t work would it?
Baz: quite. I’ve just chucked together a wee plugin to make it explicit that I’m setting default values for certain attributes. It’s completely undocumented and doesn’t have a stand-alone test suite, but you can find it here:
http://svn.rubaidh.com/plugins/trunk/default_values
Basically you stick the following in your model:
default_values :foo => 3, :bar => “apples”, :baz => false
and it does the right thing
Cheers fella,
I will take a look and update this article accordingly.
Thanks, I’ve been looking for this functionality for a while now!