Rails 1.2 introduced native Decimal-support in ActiveRecord. This enabled us to use decimal-columns in migrations without the need to drop back to SQL. Also the Decimal-columns are now returned as BigDecimal-objects by ActiveRecord. During the migration from 1.1 to 1.2, the tests of two applications suddenly showed the follwing problem:
TypeError: BigDecimal can't be coerced into BigDecimal
The problem was caused by the serialization of a data-structure including BigDecimals because YAML currently can't store BigDecimals.
A short search on the web showed other people with the
same problem and some good advice and also a
ticket but no solution which transparently loads the BigDecimal-objects back from the YAML-file.
The source of the problem is that BigDecimal has no YAML-representation and so is YAMLed with the standard approach of a generic object. But a YAML line like "--- !ruby/object:BigDecimal {}" doesn't help a lot when reconstructing the number.
So I want to share my workaround:
[geshi lang=ruby]
require 'yaml'
require 'bigdecimal'
class BigDecimal
def to_yaml(opts={})
YAML::quick_emit(object_id, opts) do |out|
out.scalar("tag:induktiv.at,2007:BigDecimal", self.to_s)
end
end
end
YAML.add_domain_type("induktiv.at,2007", "BigDecimal") { |type, val|
BigDecimal.new(val)
}
[/geshi]
I just open BigDecimal and redefine the output of to_yaml with a custom type and the string-representation of the BigDecimal. As I am not sure what the type of BigDecimal will be in the official version I just used a tag including my domain name. For me it's not a big deal, as I am using YAML just for caching. If you use YAML for persistent storage, be aware of a potentially conflicting official solution at some point in the future.
For the Rails-people out there I have packaged it up in a
small plugin.
(As usual, use everything at your own risk!)