Default values in your models

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.

This entry was posted on Thursday, January 18th, 2007 at 9:17 pm and is filed under Designing Great Software, Ruby on Rails and Software Development. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

6 Responses to “Default values in your models”

  1. Michael Says:

    Thanks!

    Though I have to say it’s the American spelling of initialise they use. So it’s “initialize”.

  2. Graeme Mathieson Says:

    By any chance was your unexplained one a boolean that you were defaulting to false?

  3. Baz Says:

    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?

  4. Graeme Mathieson Says:

    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

  5. Baz Says:

    Cheers fella,

    I will take a look and update this article accordingly.

  6. Alex Says:

    Thanks, I’ve been looking for this functionality for a while now!

Leave a Reply