19

Possible Duplicate:
Rails 3. How do display two decimal places in edit form?

I know I can use sprintf to limit to two decimal places.

When I redisplay the prices in a form or just in a table, sometimes I get 80, instead of 80.00. Wouldn't be better to just store the price with the two decimal places from the very moment the price is entered in the database? That way, whenever it's displayed, it will ALWAYS show the two decimal places. If so, how?

Community
  • 1
  • 1
leonel
  • 10,106
  • 21
  • 85
  • 129
  • 5
    This is not a duplicate question - question is how to round in the MODEL not in the view (as in "dupe" question). In the model you can use round(2) but it won't FORCE two decimal places in a string response. To force two decimal places use sprintf('%.2f',number) - but this won't round (it just truncates). Most of the time when working with currency you would want to round then use sprintf on the final output. Answering here because question is closed to answers, because flagged as dupe. – Eskim0 Oct 07 '13 at 20:10
  • Voting to reopen for reason stated by @Eskim0. The model and edit forms are different places and although the core of the answers are similar/the same, the way of implementing differs (e.g. you wouldn't put `value: ...` in the model as could be done in an html form – stevec Dec 17 '22 at 06:27

4 Answers4

41

You can simply use x.round(2) when displaying the number - that will always display two decimal places. It's generally recommended to store prices as integers in the backend database because they are handled better when you need a really high level of precision. In this case though, you can choose to go either way.

ankit
  • 3,328
  • 3
  • 26
  • 39
21

If it's a :float or :decimal, 80 and 80.00 in Ruby are going to be the same thing (as will 80.0000). The latter isn't "stored" with more decimal places, and trailing zeroes only make sense in the view. You can use sprintf like you said, or you can use Rails' handy number_with_precision helper:

<%= number_with_precision price, :precision => 2 %>

Here's another SO question on this topic, by the way. @Matthew Rudy is right about one thing: For money columns you should be using :decimal.

If you're really committed to not having this in your view, you could use something like Draper to apply decorators to your attributes (which will merely move your number_with_precision call out of the way and into a new Decorator class), but it's probably overkill in this instance.

Community
  • 1
  • 1
Jordan Running
  • 102,619
  • 17
  • 182
  • 182
10

You should try using the :decimal type of database field, with the :scale set to 2

To add a decimal column to a new table;

create_table :my_table do |t|
  t.decimal :my_column, :scale => 2
end

To add a column to an existing table;

add_column :my_table, :my_column, :decimal, :scale => 2

It is wise to have precisions since some database does not have precision defaults. Such as postgresql:

 add_column :my_table, my_column, precision: 30, scale: 2
Lesly Revenge
  • 894
  • 10
  • 16
Matthew Rudy
  • 16,724
  • 3
  • 46
  • 44
  • Used this but it only allows 1 decimal place `change_column :items, :cost, :decimal, :precision => 10, :scale => 2`. weird. – leonel Oct 14 '11 at 19:51
  • I enter amounts with 4 decimal places, and it allows them, shouldn't only store 2 decimal places? – leonel Oct 14 '11 at 19:51
  • does not work for me without supplying `:precision`, if i put `:scale` only I get 0 for precision. – GiH Mar 26 '13 at 16:06
8

For this I use the number_to_currency formater. Since I am in the US the defaults work fine for me.

<% price = 45.9999 %>
<price><%= number_to_currency(price)%></price>
=> <price>$45.99</price>

You can also pass in options if the defaults don't work for you. Documentation on available options at api.rubyonrails.org

codesponge
  • 220
  • 2
  • 8