The Standard Library

Digging into those helpful libraries that ship with Ruby.

30

JUL
2006

PStore Meets YAML

I love the PStore standard library. It's a very graceful interface to get some fairly robust serialized mini-database handling in just a few lines. With it you get:

  1. Transactions with commit and rollbacks (automatic on exception).
  2. File locking, shared and exclusive.
  3. Multiprocessing safety.

PStore does even more, including some file mode checking and MD5 hashing to avoid unneeded writes, but the above are the major selling points for me.

Now, if I had to level any one complaint at PStore, it would be that because it uses Marshal under the hood it doesn't create files you can easily browse or tweak by hand. (Marshal is a feature, don't get me wrong. It's fast, which is very helpful.) Sometimes though I want PStore protection with the YAML file format.

I'm embarrassed to admit that I use to use a hack for this:

require "pstore"
require "yaml"
class PStore; Marshal = YAML; end

That just redefines the Marshal constant in a scope that should only alter PStore. The library only uses dump() and load() and those methods work the same with Marshal and YAML.

Ready for the punch-line?

I learned today that my fragile hack has been in vain, no matter how clever it may be. YAML ships with a file that will load and modify PStore for you. Usage is as simple as:

require "yaml/store"

From there just replace your PStore.new() calls with YAML::Store.new() and you're in business. YAML::Store is a subclass of PStore, so you won't need to change one bit of the API to get PStore robustness with YAML output.

Comments (2)
  1. rahul benegal
    rahul benegal February 15th, 2007 Reply Link

    Dear James,

    I have been using ruby for some time and had something to say about PStore and YAML. But first a question:

    1. I am using YAML files for configuration of applications (key-value pairs).

      However, just as in our Unix config files we may first mention a variable such as GEM_HOME and then use that later (e.g. $GEM_HOME/bin), I was wanting a user to be able to define a minimum number of settings in the config file. The rest maybe derived from the above.

      However, there doesn't seem to be any YAML syntax for that. Is there some standard solution for the problem, or is my approach of using hashes wrong?

    2. The second point I might mention is that I tried using YAML to store data structures that contain HTML data. However, the loads would fail because the HTML would have : and many other such characters that YAML could not take care of. (I had tried EscapeHTML but that also did not solve my issue.)

      Then I discovered PStore and used it to store the structures, and all is fine. Of course, that means that I cannot view or hand-edit the PStore file. (XML if I recall, has something like CDATA or some syntax for specifying that the following is not to be interpreted until some set of closing characters come.)

    Thanks a lot. It seems you have been very busy for a longtime. Your blog is a great inspiration for us. Please keep blogging.

    1. Reply (using GitHub Flavored Markdown)

      Comments on this blog are moderated. Spam is removed, formatting is fixed, and there's a zero tolerance policy on intolerance.

      Ajax loader
    2. James Edward Gray II
      James Edward Gray II February 15th, 2007 Reply Link

      I think Hashes are a fine choice. One way to handle this would be to merge the user settings with an existing defaults Hash:

      >> DEFAULT = {:one => "default one", :two => "default two"}
      => {:one=>"default one", :two=>"default two"}
      >> user = {:two => "override two"}
      => {:two=>"override two"}
      >> settings = DEFAULT.merge(user)
      => {:one=>"default one", :two=>"override two"}
      

      As for YAML generating content it cannot parse, the best thing to do would be to reduce it to a minimal case where it fails and report it as a bug on the Ruby Core mailing list.

      Hope that helps.

      1. Reply (using GitHub Flavored Markdown)

        Comments on this blog are moderated. Spam is removed, formatting is fixed, and there's a zero tolerance policy on intolerance.

        Ajax loader
Leave a Comment (using GitHub Flavored Markdown)

Comments on this blog are moderated. Spam is removed, formatting is fixed, and there's a zero tolerance policy on intolerance.

Ajax loader