Skip to content
Browse files

Don't require BigDecimal serialization extension

Rails currently provides an extension to BigDecimal that redefines how
it is serialized to YAML. However, as noted in #12467, this does not
work as expected. When ActiveSupport is required, BigDecimal YAML
serialization does not maintain the object type. It instead ends up
serializing the number represented by the BigDecimal itself which, when
loaded by YAML later, becomes a Float:

```ruby
require 'yaml'
require 'bigdecimal'

yaml = BigDecimal('13.37').to_yaml
YAML.load(yaml).class

require 'active_support/all'

yaml = BigDecimal('13.37').to_yaml
YAML.load(yaml).class
```

@tenderlove posits that we should deprecate the custom BigDecimal
serialization and let Ruby handle it. For the time being, users who
require this serialization for backwards compatibility can manually
`require 'active_support/core_ext/big_decimal/yaml_conversions'`.

This will close #12467 and deprecate the custom BigDecimal#to_yaml.

Signed-off-by: David Celis <me@davidcel.is>
  • Loading branch information...
1 parent 9b2a017 commit 85d820b1693a52faddf1f838512e132906272e41 @davidcelis davidcelis committed Jan 31, 2014
View
8 activesupport/CHANGELOG.md
@@ -1,3 +1,11 @@
+* Deprecate custom `BigDecimal` serialization
+
+ Deprecate the custom `BigDecimal` serialization that is included when requiring
+ `active_support/all` as a fix for #12467. Let Ruby handle YAML serialization
+ for `BigDecimal` instead.
+
+ *David Celis*
+
* Maintain the current timezone when calling `wrap_with_time_zone`
Extend the solution from the fix for #12163 to the general case where `Time`
View
8 activesupport/lib/active_support/core_ext/big_decimal/conversions.rb
@@ -1,15 +1,7 @@
require 'bigdecimal'
require 'bigdecimal/util'
-require 'yaml'
class BigDecimal
- YAML_MAPPING = { 'Infinity' => '.Inf', '-Infinity' => '-.Inf', 'NaN' => '.NaN' }
-
- def encode_with(coder)
- string = to_s
- coder.represent_scalar(nil, YAML_MAPPING[string] || string)
- end
-
# Backport this method if it doesn't exist
unless method_defined?(:to_d)
def to_d
View
13 activesupport/lib/active_support/core_ext/big_decimal/yaml_conversions.rb
@@ -0,0 +1,13 @@
+ActiveSupport::Deprecation.warn 'core_ext/big_decimal/yaml_conversions is deprecated and will be removed in the future.'
+
+require 'bigdecimal'
+require 'yaml'
+
+class BigDecimal
+ YAML_MAPPING = { 'Infinity' => '.Inf', '-Infinity' => '-.Inf', 'NaN' => '.NaN' }
+
+ def encode_with(coder)
+ string = to_s
+ coder.represent_scalar(nil, YAML_MAPPING[string] || string)
+ end
+end
View
11 activesupport/test/core_ext/big_decimal/yaml_conversions_test.rb
@@ -0,0 +1,11 @@
+require 'abstract_unit'
+require 'active_support/core_ext/big_decimal/yaml_conversions'
+
+class BigDecimalYamlConversionsTest < ActiveSupport::TestCase
+ def test_to_yaml
+ assert_match("--- 100000.30020320320000000000000000000000000000001\n", BigDecimal.new('100000.30020320320000000000000000000000000000001').to_yaml)
+ assert_match("--- .Inf\n", BigDecimal.new('Infinity').to_yaml)
+ assert_match("--- .NaN\n", BigDecimal.new('NaN').to_yaml)
+ assert_match("--- -.Inf\n", BigDecimal.new('-Infinity').to_yaml)
+ end
+end
View
9 activesupport/test/core_ext/bigdecimal_test.rb
@@ -2,18 +2,11 @@
require 'active_support/core_ext/big_decimal'
class BigDecimalTest < ActiveSupport::TestCase
- def test_to_yaml
- assert_match("--- 100000.30020320320000000000000000000000000000001\n", BigDecimal.new('100000.30020320320000000000000000000000000000001').to_yaml)
- assert_match("--- .Inf\n", BigDecimal.new('Infinity').to_yaml)
- assert_match("--- .NaN\n", BigDecimal.new('NaN').to_yaml)
- assert_match("--- -.Inf\n", BigDecimal.new('-Infinity').to_yaml)
- end
-
def test_to_d
bd = BigDecimal.new '10'
assert_equal bd, bd.to_d
end
-
+
def test_to_s
bd = BigDecimal.new '0.01'
assert_equal '0.01', bd.to_s

0 comments on commit 85d820b

Please sign in to comment.
Something went wrong with that request. Please try again.