3

I'm storing a decimal in rails and I need to have it display as a currency as such:

11.1230 => "$11.123"
11.1000 => "$11.10"
11.0100 => "$11.01"
11.1234 => "$11.1234"

Any easy way to do this?

Phrogz
  • 296,393
  • 112
  • 651
  • 745
Jake
  • 39
  • 1
  • 4
  • 1
    I think your rules might need to be clarified. Is it "at least two decimal places, but more if necessary"? – Phrogz May 11 '11 at 18:35

4 Answers4

5

Edit: Looks like this is Rails 3 specific, as Rails 2's number_with_precision method doesn't include the strip_insignificant_zeros option:

You can pass some options to number_to_currency (a standard Rails helper):

number_to_currency(11.1230, :precision => 10, :strip_insignificant_zeros => true)
# => "$11.123"

You need to provide a precision in order for the strip_insignificant_zeros option to work, though, otherwise the underlying number_with_precision method never gets called.

Dylan Markow
  • 123,080
  • 26
  • 284
  • 201
  • I actually get $11.1230000000 when I run that example – Jake May 11 '11 at 18:13
  • @dmarkow I don't see the `strip_insignificant_zeros` option in [the documentation](http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html#method-i-number_to_currency). – Phrogz May 11 '11 at 18:34
  • @Jake, you need to lower the `:precision` if you want less zeroes. Those 0's are significant digits, so they won't be tossed: http://en.wikipedia.org/wiki/Significant_figures – McStretch May 11 '11 at 18:35
  • @Phrogz: It's not documented, but if you specify a precision, it passes ALL the options into number_with_precision (which does support the strip_insignificant_zeros option). (at least in Rails 3) – Dylan Markow May 11 '11 at 19:46
  • @Austin: I'm pretty sure he wants to display more than just two decimal places if the number warrants it. I just picked an arbitrary "high" number. – Dylan Markow May 11 '11 at 19:47
  • @Jake: I was doing this on Rails 3; it's probably different for Rails 2 (assuming that's what you're using) – Dylan Markow May 11 '11 at 19:49
5
def pad_number( number, min_decimals=2 )
  s = "%g" % number
  decimals = (s[/\.(\d+)/,1] || "").length
  s << "." if decimals == 0
  s << "0"*[0,min_decimals-decimals].max
end
puts [ 11.123, 11.1, 11.01, 11.1234, 11 ].map{ |n| pad_number(n) }
#=> 11.123
#=> 11.10
#=> 11.01
#=> 11.1234
#=> 11.00
Phrogz
  • 296,393
  • 112
  • 651
  • 745
4

If you want to store as a float, you can use the number_to_currency(value) method in yours views for printing something that looks like $.

Correct me if I'm wrong (as I've rarely dealt with currency) but I think the conventional wisdom is to store dollar values as integers. That way you won't have to deal with funky float math.

Kombo
  • 2,371
  • 3
  • 34
  • 64
  • 3
    Yes, store the value in cents, or whatever the smallest currency value is, as integers to avoid rounding errors. Then adjust for the desired dollar amount as a last step by dividing by 100 to return it to the normal $0.00 format. – the Tin Man May 11 '11 at 18:18
  • I think best practice is to use decimal -- there's no rounding issues and less work for displaying. see: http://stackoverflow.com/questions/1019939/ruby-on-rails-best-method-of-handling-currency-money – Stewart Johnson Feb 05 '12 at 01:31
-1

So, convert it to three decimal fraction digits and then remove the final one if and only if it's a zero.

s.sub(/0$/, '')
DigitalRoss
  • 143,651
  • 25
  • 248
  • 329