The problems with Bignums in recent YAMLs have been discussed(*), but
does anyone have a patch that can be loaded in ruby code to get around
it?
This just turned into a minor disaster for me…
$ ruby -v
ruby 1.8.4 (2005-12-24) [i686-linux]
$ ruby -r yaml -e ‘y 1234567890’
— !ruby/object:Bignum 1234567890
$ ruby -r yaml -e ‘YAML.load 1234567890.to_yaml’
/usr/local/lib/ruby/1.8/yaml.rb:133:in transfer': allocator undefined for Bignum (TypeError) from /usr/local/lib/ruby/1.8/yaml.rb:133:in
load’
from -e:1
(*)
http://groups.google.com/group/comp.lang.ruby/browse_frm/thread/4d62fa19fc7f4ffe/2331cd65b83bffe2?q=YAML+Bignum&rnum=1#2331cd65b83bffe2
Joel VanderWerf wrote:
/usr/local/lib/ruby/1.8/yaml.rb:133:in transfer': allocator undefined for Bignum (TypeError) from /usr/local/lib/ruby/1.8/yaml.rb:133:in
load’
from -e:1
(*)
http://groups.google.com/group/comp.lang.ruby/browse_frm/thread/4d62fa19fc7f4ffe/2331cd65b83bffe2?q=YAML+Bignum&rnum=1#2331cd65b83bffe2
Answering my own question, but it’s a hack…
class Bignum
def to_yaml( opts = {} )
super.sub(/!ruby/object:Bignum /, “”)
end
end
s = 1000000000000000.to_yaml
puts s
p YAML.load(s)
OUTPUT:
— 1000000000000000
1000000000000000
Hello,
The latest ruby cvs seems to work ok?
bash-3.00# ruby -r yaml -e ‘y 1234567890000000000000’
— 1234567890000000000000
bash-3.00# ruby -r yaml -e ‘YAML.load 1234567890000000000000.to_yaml’
bash-3.00# ruby -v
ruby 1.8.4 (2006-03-04) [i386-solaris2.10]
Ville Mattila wrote:
Hello,
The latest ruby cvs seems to work ok?
bash-3.00# ruby -r yaml -e ‘y 1234567890000000000000’
— 1234567890000000000000
bash-3.00# ruby -r yaml -e ‘YAML.load 1234567890000000000000.to_yaml’
bash-3.00# ruby -v
ruby 1.8.4 (2006-03-04) [i386-solaris2.10]
That’s good to hear. I’d rather not have to install from cvs in all my
locations, but my workaround didn’t work (see below), so maybe that’s
necessary.
$ ruby
require ‘yaml’
class Bignum
def to_yaml( opts = {} )
super.sub(/!ruby/object:Bignum /, “”)
end
end
h={}
h[1] = 1000000000000000
y h
-:5:in to_yaml': private method
sub’ called for
#YAML::Syck::Scalar:0xb7b6d03c (NoMethodError)
from /usr/local/lib/ruby/1.8/yaml/rubytypes.rb:41:in to_yaml' from /usr/local/lib/ruby/1.8/yaml/rubytypes.rb:40:in
to_yaml’
from /usr/local/lib/ruby/1.8/yaml/rubytypes.rb:39:in to_yaml' from /usr/local/lib/ruby/1.8/yaml.rb:387:in
quick_emit’
from /usr/local/lib/ruby/1.8/yaml/rubytypes.rb:38:in to_yaml' from /usr/local/lib/ruby/1.8/yaml.rb:117:in
dump’
from /usr/local/lib/ruby/1.8/yaml.rb:428:in `y’
from -:11
Joel VanderWerf [email protected] writes:
h={}
h[1] = 1000000000000000
y h
This works fine with CVS ruby, without your special hack.
So probably the cvs is way to go.
irb(main):001:0> require ‘yaml’
=> true
irb(main):002:0>
irb(main):003:0* h={}
=> {}
irb(main):004:0> h[1] = 1000000000000000
=> 1000000000000000
irb(main):005:0> y h
1: 1000000000000000
=> nil
Joel,
If it’s helpfuly, here’s the small patch we’ve been using in Gentoo
that I believe fixes this:
— ext/syck/rubyext.c 27 Sep 2005 22:57:52 -0000 1.30.2.15
+++ ext/syck/rubyext.c 5 Oct 2005 10:24:16 -0000
@@ -1142,6 +1142,9 @@
}
else if ( !NIL_P( target_class ) )
{
-
if (subclass == rb_cBignum)
-
obj = rb_str2inum(val, 10);
-
else
obj = rb_obj_alloc( subclass );
if ( rb_respond_to( obj, s_yaml_initialize ) )
{
Joel VanderWerf wrote:
/usr/local/lib/ruby/1.8/yaml.rb:133:in transfer': allocator undefined for Bignum (TypeError) from /usr/local/lib/ruby/1.8/yaml.rb:133:in
load’
from -e:1
(*)
http://groups.google.com/group/comp.lang.ruby/browse_frm/thread/4d62fa19fc7f4ffe/2331cd65b83bffe2?q=YAML+Bignum&rnum=1#2331cd65b83bffe2
I think this workaround actually works:
if RUBY_VERSION == “1.8.4”
class Bignum
def to_yaml( opts = {} )
YAML::quick_emit( nil, opts ) { |out|
out.scalar( nil, to_s, :plain )
}
end
end
end
…that sure beats compiling cvs for several platforms and distributing
it to users.