1. Technology
You can opt-out at any time. Please refer to our privacy policy for contact information.

How Can I Store Key/Value Pairs in Ruby?

By

Question: How Can I Store Key/Value Pairs in Ruby?

When you need key/value storage in Ruby, it's easy to reach for hashes every time. However, you do have some other choices here that can make your code more readable and faster.

Answer:

Your first alternative option for key/value storage is the Struct. The Struct class is like a struct in C or C++. It has a set of variables you can assign to, and nothing else. In Ruby, it's just a shortcut to creating an empty class and adding some attr_accessor statements and a contructor to assign to the attributes.

 #!/usr/bin/env ruby
 
 # Define the struct
 Item = Struct.new( :name, :id, :price )
 
 # Assign from constructor
 i = Item.new( "Watermelons", 1337, "$5.40" )
 puts i.name
 puts i.id
 puts i.price
 
 # Or assign after constructor
 i.name = "Blue cheese"
 
 # This code is equivalent, but more verbose
 class AnotherItem
   attr_accessor :name, :id, :price
 
   def initialize( *args )
     @name, @id, @price = *args
   end
 end
 
 p = AnotherItem.new( "Sardines", 31337, "$0.99" )
 puts p.name
 puts p.id
 puts p.price
 

As you can see, a Struct can replace a hash and store objects in a key/value scheme. This should also be faster since no hash values have to be calculated. Instead of calculating a hash value and doing a lookup in the hash for the key, a simple method lookup will be performed. However, this doesn't let you define new attributes on the fly. This is where OpenStruct comes in.

An OpenStruct is like a Struct, except you don't have to define a list of attributes on construction. Instead, the first time you try to assign to an attribute that doesn't yet exist, the OpenStruct class will create it for you. This gives you all the benefits of hashes without the limitations of a Struct.

 #!/usr/bin/env ruby
 require 'ostruct'
 
 i = OpenStruct.new
 i.name = "Watermelons"
 i.id = 1337
 i.price = "$5.40"
 
 puts i.name
 puts i.id
 puts i.price
 

There is, however, one huge caveat when using these classes. The attributes in these examples were chosen very carefully. If you run the second example, you'll see a warning about using the object_id method instead of id, and the id returned is wrong. What is this all about?

Well, these are normal objects, after all. You still have to worry about the methods it already inherited from the Object class. In the first example, everything appears to have worked. However, since Struct creates new methods for each attribute, it's overwritten Object#id on the object.

The second example is a little more tricky. When you try to use any assignment to an attribute, it first checks to see if that method exists. Since Object#id exists, it assumes is can assign to it and tries to. This doesn't work at all, and the value you get when you read the id attribute is incorrect. So always watch your attribute names carefully! Refer to the Object documentation for a list of attribute names you cannot use.

  1. About.com
  2. Technology
  3. Ruby
  4. Beginning Ruby
  5. Ruby's Basic Features
  6. Storing Key/Value Pairs in Ruby - Structs and OpenStructs

©2014 About.com. All rights reserved.