views:

765

answers:

4

Looking on SO, I see that the preferred way to currency using RoR is using decimal(8,2) and to output them using number_to_currency();

I can get my numbers out of the DB, but I'm having issues on getting them in.

Inside my update action I have the following line:

if @non_labor_expense.update_attributes(params[:non_labor_expense]) 
puts YAML::dump(params) 

The dump of params shows the correct value. xx,yyy.zz , but what gets stored in the DB is only xx.00

What do I need to do in order to take into account that there may be commas and a user may not enter .zz (the cents). Some regex and for comma? how would you handle the decimal if it were .2 versus .20 .

There has to be a builtin or at least a better way.

My Migration (I don't know if this helps):

class ChangeExpenseToDec < ActiveRecord::Migration
    def self.up
       change_column :non_labor_expenses, :amount, :decimal, :precision => 8, :scale => 2
    end

    def self.down
          change_column :non_labor_expenses, :amount, :integer
    end
end
+2  A: 

It might depend on what DBMS you're using, but as far as I know, decimal fields won't accept commas (at least not as separators; there might be a way to have the database accept a comma as a decimal point rather than a period). What you will have to do is remove the commas from your numbers (in a before_save or before_validation filter, perhaps), and then when you display the number, add the commas back in.

before_validation :strip_commas_from_non_labor_expense

def strip_commas_from_non_labor_expense
  self.non_labor_expense = self.non_labor_expense.to_s.gsub(/,/, '').to_f
end

Then use number_to_currency when you want to display the expense amount formatted with comma separated groups and two decimal places, as you mentioned:

<%
  non_labor_expense = ... # get value from your model
  puts number_to_currency(non_labor_expense, :precision => 2, :separator => ',')
%>
Daniel Vandersluis
I tried your before_validation and the function in the model, and I puts YAML::dump(self.amount) but the amount is already truncated. I get the following error: private method `gsub!' called for #<BigDecimal:7bf69fc,'0.22E2',4(8)> when I change your code to: self.amount.gsub!('/,/', '')Any ideas?
easement
If I do self.amount.to_s.gsub!('/,/', '') then gsub! works, but doing a dump before I make that call, it appears as if the value is already truncated. any ideas?
easement
Sorry, I updated my answer. The quotes are not needed around the regular expression (I'm in PHP mode today, heh) and `gsub` should be used rather than `gsub!` because the latter replaces the string with `nil` if no replace was made. Also, I added `to_f` at the end to put it back into a float.
Daniel Vandersluis
+1  A: 

I tried Daniel's before_validation idea and I just couldn't get it to work. It seemed that the by the time I get to the before_validation the input has already been converted. The solution I went with was to override the method for the column, and strip the commas there:

def profit=(num)
  num.gsub!(',','') if num.is_a?(String)
  self[:profit] = num
end
Guy C
A: 

Here you can find a code snippet that will make any decimal column accept values with the comma as decimal separator:

http://gem-session.com/2010/03/how-to-use-the-comma-as-decimal-separator-in-rails-activerecord-columns-and-text-fields

Henning
+1  A: 

Checkout the delocalize gem:

http://github.com/clemens/delocalize

muitocomplicado