Ruby on Rails - Валюта: запятые вызывают проблему

Глядя на SO, я вижу, что предпочтительным способом валюты с использованием RoR является использование десятичного числа (8,2) и их вывод с помощью number_to_currency();

Я могу получить свои номера из БД, но у меня проблемы с их вводом.

Внутри моего действия обновления у меня есть следующая строка:

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

Дамп параметров показывает правильное значение. xx,yyy.zz , но в БД сохраняется только xx.00

Что мне нужно сделать, чтобы учесть, что могут быть запятые и пользователь не может вводить .zz (центы). Какое-то регулярное выражение и запятая? как бы вы справились с десятичной дробью, если бы это было .2 против .20 .

Должен быть встроенный или, по крайней мере, лучший способ.

Моя миграция (я не знаю, поможет ли это):

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

person easement    schedule 25.01.2010    source источник
comment
.2 и .20 — это одно и то же число, поэтому не важно, как вы его храните, важно только то, как вы его отображаете.   -  person Daniel Vandersluis    schedule 25.01.2010
comment
Верно. Первая проблема заключается в том, что я теряю данные после запятой. Вы говорите, что как только я решу это, .2 и .20 разрешатся сами собой в зависимости от того, как они хранятся в БД?   -  person easement    schedule 25.01.2010
comment
Смотрите мой ответ; в основном, вы сохраняете число в базе данных как прямое (неформатированное) десятичное число, а затем форматируете его по своему усмотрению, когда вам нужно его отобразить.   -  person Daniel Vandersluis    schedule 25.01.2010


Ответы (4)


Это может зависеть от того, какую СУБД вы используете, но, насколько я знаю, десятичные поля не будут принимать запятые (по крайней мере, не в качестве разделителей; может быть способ заставить базу данных принимать запятую как десятичную точку, а не Период). Что вам нужно сделать, так это удалить запятые из ваших чисел (возможно, в фильтре before_save или before_validation), а затем, когда вы отображаете число, добавить запятые обратно.

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

Затем используйте number_to_currency, если вы хотите отобразить сумму расходов в формате группы, разделенные запятыми, и два десятичных знака, как вы упомянули:

<%
  non_labor_expense = ... # get value from your model
  puts number_to_currency(non_labor_expense, :precision => 2, :separator => ',')
%>
person Daniel Vandersluis    schedule 25.01.2010
comment
Я попробовал ваш before_validation и функцию в модели, и я поставил YAML::dump(self.amount), но сумма уже усечена. Я получаю следующую ошибку: частный метод `gsub!' вызывает #‹BigDecimal:7bf69fc,'0.22E2',4(8)›, когда я изменяю ваш код на: self.amount.gsub!('/,/', '') Есть идеи? - person easement; 25.01.2010
comment
Если я сделаю self.amount.to_s.gsub!('/,/', ''), то gsub! работает, но делая дамп до того, как я сделаю этот вызов, кажется, что значение уже усечено. Любые идеи? - person easement; 25.01.2010
comment
Извините, я обновил свой ответ. Кавычки вокруг регулярного выражения не нужны (сегодня я в режиме PHP, хех), и следует использовать gsub, а не gsub!, потому что последний заменяет строку на nil, если замена не была сделана. Кроме того, я добавил to_f в конце, чтобы вернуть его в число с плавающей запятой. - person Daniel Vandersluis; 25.01.2010
comment
Я испытал, что это сокращение десятичных значений. - person Magne; 06.10.2011

Я попробовал идею Дэниела before_validation и просто не смог заставить ее работать. Казалось, что к тому времени, когда я доберусь до проверки перед_проверкой, ввод уже будет преобразован. Решение, которое я выбрал, состояло в том, чтобы переопределить метод для столбца и убрать запятые:

def profit=(num)
  num.gsub!(',','') if num.is_a?(String)
  self[:profit] = num
end
person Guy C    schedule 31.01.2010
comment
Работает, но предложение Хеннинга является DRY'er, если вы собираетесь преобразовать , в . для нескольких входов в приложении. - person Magne; 06.10.2011
comment
Это работает, вы также можете подключиться к attribute_before_type_cast в обратном вызове before_validation, например. self.profit = profit_before_type_cast.to_s.gsub(/,/,'') - person Mark G.; 18.03.2015
comment
Это спасительный ответ :) - person Rokibul Hasan; 02.05.2016

Оформить заказ delocalize gem:

http://github.com/clemens/delocalize

person muitocomplicado    schedule 29.03.2010

Здесь вы можете найти фрагмент кода, который заставит любой десятичный столбец принимать значения с запятой в качестве десятичного разделителя:

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

person Henning    schedule 21.03.2010