2.4 Serializing

Serializing? Cerealizing? What?

At some point, you will want your Ruby programs to talk to other programs. Usually, if your program is talking to another program, communication between them is done through an Application Programming Interface or API. Don't let that article scare you. An API is just a generic term for any interface which allows one program to either read data from another program or write data to another program. Or both!

One of the simplest interfaces two Ruby programs can share is a file. The first program will transform some of its objects into a string and then write those strings to a file. The second program will look for the file in a shared location (this is particularly easy if both programs are running on the same computer), read it, and turn the strings in the file back into Ruby objects. Take a look back at the Ruby Primer's I/O chapter if you need a refresher on Ruby's file libraries.

This basic concept (transferring data between programs) is essentially what we're referring to when we say "serializing". By turning our Ruby objects into strings we have made them serial: the objects are all lumped together as a string of chracters, one character after another. We've actually covered one method of serialization already: Object#to_s. In the exercise below, try to write a to_s method that produces a string from_s understands.

Hint

Note that `from_s` is using the `each_line` method. To insert a newline within a string, use the '\n' character literal.

Output Window

While that strategy does work, it's quite cumbersome. The from_s method is big, ugly, and fragile. Try sending it some invalid values! It won't be very happy. It's also not very generic; we would have to write a custom from_s method for every new class. Ugh! Let's not even think about that. Instead, let's move on to Ruby's built-in solution to this problem.

Dumping and loading

We want some way of automatically transforming any Ruby object into a serialized form. There are a number of serialization formats we could use. You may have heard of XML, json, or YAML. Ruby can produce any of these formats (they're all strings, by the way) but we'll specifically take a look at YAML since it's built right into the Ruby language. Here, YAML::dump and YAML::load do all the heavy lifting for us.

Example Code:

Output Window

Super cool, right? Much easier than the hand-made solution.

Press "start" to save your game

As you've probably noticed by now, the concept of transferring data between programs isn't limited to two different programs. The examples above were reading and writing their own serialized formats. Philosophically, if we write some Ruby objects to a file, close our program, then open our program later and read those same objects back, we're really transferring data between two programs: our program at time T and our program at time T+n... in the future! This is nothing special, really. It's the way your wordprocessor opens on Thursday a file you created on Monday. But it sounds fancier this way.

Let's use this concept to extend our Ogre example. As you could see from the Ogre class, YAML understands any Ruby object you throw at it. This means we don't need to put the YAML method calls in the Ogre class itself -- interacting with YAML can happen at a much higher level, like our save_game method below. Finish the exercise so that the game characters can be saved to disk and loaded later. To save a YAML string to disk, use the handy GameFile#write(yaml) and GameFile#read methods I've written for you. GameFile.new accepts one parameter, which should be a .yaml file.

Hint

`GameFile.new(file)` will need to access the same file in both `save_game` and `load_game`.

Output Window

Congratulations, guest!


% of the book completed

or

This lesson is Copyright © 2011-2024 by Jasim A Basheer