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

Samstag, 1. Oktober 2011

Announcing Level Clone War

The second level for the programming game Zero-X is ready. I'm proud to announce the 2nd level Clone War.

The first level Greenfields introduced basic sensors and actions and showed how to control a single population. With Clone War these sensors and actions will be extended. But we also have a new action, now it is possible to split a population.

Split does two things, first it splits the population into two equal sized populations and then moves the new created population to a field of your choice. Split looks the same as move_to it takes a field or position as parameter for the new population.

new_population = old_population.split(field)
new_population = old_population.split(-1, 0)
new_population = old_population.split(x: 1, y: 1)

As we may have multiple populations now, you need to specify the population you want to apply the action:

population_a.look_around
population_b.move_to 1, 1
population_c.size
population_c.resource

As you can see the new introduced action changes quite a lot. In the next blog post I will describe how some well-known actions have been extended.

For more details see the documentation.