2

I have a model product, that model have attribute price with decimal type (:precision => 20, :scale => 2) In the form I use format for price field that looks like : 3.000,00, When submitting the form, price change to 3.00 . I want the price to be 3,000.00, not 3.00

Test with rails console

irb(main):001:0> p = Product.create(:price => "3.000,00")   ←[1m←[36m
(0.0ms)←[0m  ←[1mBEGIN←[0m   ←[1m←[35mSQL (72.0ms)←[0m  INSERT INTO
"products" ("created_at", "price" "updated_at") VALUES ($1, $2, $3)
RETURNING "id"  [["created_at", Tue, 29 Apr 2 014 14:07:25 WIB
+07:00], ["price", #<BigDecimal:4c218f0,'0.3E1',9(18)>], ["updated_at", Tue, 29 Apr 2014 14:07:25 WIB +07:00]]   ←[1m←[36m
(11.0ms)←[0m  ←[1mCOMMIT←[0m
=> #<Product id: 8, price: #<BigDecimal:4bd5588,'0.3E1',9(18)>, created_at: "20 14-04-29 07:07:25", updated_at: "2014-04-29 07:07:25">
 
irb (main):002:0> p.price.to_s
=> "3.0"

I have tried with gsub for change comma to point on before_save and store to database, but price always change to 3.00 on database.

  before_save :comma_to_delimiter

  def comma_to_delimiter
    self.price = self.price.gsub(/[.,]/, '.' => ',', ',' => '.')
  end

I want like this : when I input 3.000,00 to field price, on database 3,000.00 and on view price 3.000,00

I can't figure out how to do that. Thanks

Note : I'm using jquery-maskMoney for field price with format :

$("#demo4").maskMoney();

<input type="text" id="demo4" data-thousands="." data-decimal="," data-prefix="R$ " />
kometen
  • 6,536
  • 6
  • 41
  • 51
GeekToL
  • 1,815
  • 1
  • 24
  • 46
  • worth reading through the rails internationalization guide http://guides.rubyonrails.org/i18n.html particularly the localize function – Ian Kenney Apr 29 '14 at 07:52

2 Answers2

4

Remove the delimiter character in your String, because when saving the data in the model, it takes '.' or ',' as a decimal delimiter. Try something like this.

before_save :format_number

def format_number
  self.price = self.price.gsub(/[.,]/, '.' => '', ',' => '.')
end

For the inverse purpose in your view you can use NumberHelper, so you can format as 'R$'

<%= number_to_currency(3000.00, unit: "R$ ", separator: ",", delimiter: ".", precision: 2) %> #=> "R$ 3.000,00"
ig10
  • 56
  • 5
  • A perfect answer, but can someone please explain how this works: self.price.gsub(/[.,]/, '' => ',', ',' => '.') ? – Kush Nov 13 '14 at 04:00
  • Well it just say, when a '.' character is found by the regexp, this should be replaced by '' , and if a ',' is matched it is replaced by '.' . Thats the interpretation that I have for it and works. – ig10 Nov 14 '14 at 17:51
0

Your formatting is the problem

You're sending a value of 3.000,00 into your db. MYSQL's decimal type is designed to put the decimal point at the center of the data. I need to learn more about maths to give you a real definition (about floating points etc), but here's what I would heed from MYSQL:

The declaration syntax for a DECIMAL column remains DECIMAL(M,D), although the range of values for the arguments has changed somewhat:

M is ......

D is the number of digits to the right of the decimal point (the scale). It has a range of 0 to 30 and must be no larger than M.

This says to me that MYSQL determines the number to store using the . Because you're sending 3.000,00, it's treating it as 3.00


Fix

Interested in the solution, I looked at Wikipedia's article on decimal handling - 24% of the world use the , as the radix point

To handle this, you'd either need to translate MYSQL to handle the ,, but this is not part of its functionality. Instead, I would attempt to translate the format before save

Although you can do this manually, this answer provided the delocalize gem

Community
  • 1
  • 1
Richard Peck
  • 76,116
  • 9
  • 93
  • 147