Montag, 31. Oktober 2011

YAML in Ruby 1.9

The other day I downloaded the production database from Zero-X to my local machine to run some tests.
Everything looked fine until I got to the game reports page, which looked wired, especially the agent views. It seemed that every empty field was occupied by an agent "00".

After digging deeper I identified the error in wrong loaded YAML records. Instead of loading a nil I got Syck::PrivateType. A null with only one ! was correctly loaded, but the data from production system had two !, which were loaded differently.

YAML.load ":a: !null"     # => {:a=>nil}
YAML.load ":a: !!null"    # => {:a=>#<Syck::PrivateType:0x000001024e6b98 ,="" @type_id="null" @value="">}

YAML::ENGINE.yamler  #=> "syck"

I tried the same tests on the production system, that runs Ubuntu 10.10 I get the following output:

YAML.load ":a: !null"     # => {:a=>nil}
YAML.load ":a: !!null"    # => {:a=>nil}

YAML::ENGINE.yamler  #=> "psych"

And voilà all data are loaded correctly! The difference is an other YAML Engine, on Mac OS X Snow Leopard Syck is used, while on Ubuntu Psych.
Some investigations later I got the answer. With Ruby 1.9.2 the standard library Syck was replaced with Psych, which depends on the libyaml library. But here it comes, only if it's found when Ruby is compiled. It still uses Sych as a fallback.

So in order to have the same behavior on my local and production system, I had first to install libyaml using ports and then recompile my Ruby.

sudo port install libyaml
rvm install ruby-1.9.2 --with-libyaml-dir=/opt/local/

You could also use homebrew, that has also the advantage that you don't have to specify the path to libyaml. Homebrew installs to /usr/local, which is checked by the install script.

brew install libyaml
rvm install ruby-1.9.2

Starting irb I still had to change to psych explicitly.

YAML::ENGINE.yamler = "psych"

Rails 3 changes automatically to psych if available.

One day later I found out, that I also could install Psych as Gem instead of recompiling Ruby.

gem install psych

UPDATE:

Some other days later, I began a new Rails project and I encountered the following conflict with psych:
../psych.bundle: warning: already initialized constant ANY
../psych.bundle: warning: already initialized constant UTF8
../psych.bundle: warning: already initialized constant UTF16LE
...

If you have psych 1.2.2 installed, than uninstall it again. Psych 1.2.3 should avoid the double laoding.
see here

Kommentare:

Graham Ashton hat gesagt…

That came in very useful, thanks.

Alessandro hat gesagt…

You're welcome