Использование Ruby on Rails У меня есть несколько полей, которые сериализованы (в основном массивы или хеши). Некоторые из них содержат BigDecimal
s. Очень важно, чтобы эти большие десятичные знаки оставались большими десятичными знаками, но Rails превращает их в поплавки. Как мне вернуть BigDecimal
назад?
В этой проблеме я обнаружил, что сериализация большого десятичного разряда в простом Ruby, без Rails, работает так, как ожидалось:
BigDecimal.new("42.42").to_yaml
=> "--- !ruby/object:BigDecimal 18:0.4242E2\n...\n"
но в консоли Rails нет:
BigDecimal.new("42.42").to_yaml
=> "--- 42.42\n"
Это число представляет собой строковое представление большого десятичного знака, поэтому оно все правильно. Но когда я его читаю, он читается как float, поэтому, даже если я конвертирую его в BigDecimal
(что-то, что я не хочу делать с ошибкой), возможно, я потеряю точность, t приемлемо для моего приложения.
Я выследил виновника до activesupport-3.2.11/lib/active_support/core_ext/big_decimal/conversions.rb
, который переопределяет следующий метод в BigDecimal:
YAML_TAG = 'tag:yaml.org,2002:float'
YAML_MAPPING = { 'Infinity' => '.Inf', '-Infinity' => '-.Inf', 'NaN' => '.NaN' }
# This emits the number without any scientific notation.
# This is better than self.to_f.to_s since it doesn't lose precision.
#
# Note that reconstituting YAML floats to native floats may lose precision.
def to_yaml(opts = {})
return super if defined?(YAML::ENGINE) && !YAML::ENGINE.syck?
YAML.quick_emit(nil, opts) do |out|
string = to_s
out.scalar(YAML_TAG, YAML_MAPPING[string] || string, :plain)
end
end
Зачем им это делать? И что еще более важно, как мне это сделать?