codahale.com٭blog

This is my old blog. My current writing is here: codahale.com

dollars_and_cents: a Rails plugin

Update: Use of this plugin is deprecated. If you’re using Rails 1.2 or higher, use the :decimal field type for your monetary values. This will provide you with fixed-point math on both the database and Rails sides of your application.


(Yes, another plugin. I’m full of them.)

One of the big problems with a database-agnostic framework like ActiveRecord is that it doesn’t have a decent data type for money. Yes, you can use a FLOAT, but then you end up charging someone $12.3000000000000001, which is just awkward. You can hard-code a database-specific type, but then your code takes a dive when you hit the bigtime and get bounced up to a DB2 backend or some nonsense. Or you could store prices as an integer value of the smallest unit possible–the cent–and do the math in the model, but then you have to write an attribute wrapper, which is boring and not very DRY. Or…

Aw snap, Coda’s hauled off and done it for you! Oh happy people! Oh frabjous day!

Installamacation

Love SVN?


./script/plugin install -x http://svn.codahale.com/dollars_and_cents/

Ambivalent about it?


./script/plugin install http://svn.codahale.com/dollars_and_cents/

Usamization

dollars_and_cents is an easy plugin to use.

Name your fields the right thing

All prices should end with _in_cents. That’s the convention I made up, and you all get to deal with it. I think it’s rational, but I think many things are rational with which other people violently disagree (e.g., my dad and I on the direction in which twisty ties should be fastened–he says clockwise, I say whatever).

In a migration or somesuch:


create_table :buyable_things do |t|
  t.column :name, :string
  t.column :price_in_cents, :integer
end

Profit

Once installed, dollars_and_cents adds a Float attribute price to the model BuyableThing. Use as you would any other attribute:


  @buyable_thing = BuyableThing.find(params[:id])
  old_price = @buyable_thing.price   # => 19.99
  @buyable_thing.price = 23.99
  new_price = @buyable_thing.price   # => 23.99

And now 2399 is stored in the database, in a nice, cross-platform format: the humble int.

(If you had a database field called tulpa_death_chant_cost_in_cents, it would add an attribute called tulpa_death_chant_cost. It’s not limited to the phrase “price”. FYI.)

All yours, under the MIT license © 2006. Woo hah.

50 comments »