Secrets of the Standard Library - Paul Battley

None of these things are actually secrets, but Paul pointed out that he's been programming Ruby for quite some time, and only discovered some of the following relatively recently.

Diving straight in, what have we got...


Let's say we have an event, represented as an ActiveRecord object...

class Event < ActiveRecord::Base
  belongs_to :opportunity

...and an Opportunity. If an Event has an Opportunity and an Opportunity has an Organization, you'll get the following methods on your objects:


That means you could call:


Hold on though, it's bad form. We've just violated the law of Demeter (the gist of which is that you can play with your friends, but you shouldn't mess with your friends' friends). You could write a wrapper method on the Event class that would return organization for you, or you could use forwardable:

require "forwardable"

class Event < ActiveRecord:: Base
  extend Forwardable
  belongs_to :opportunity

  def_delegators :opportunity, :organization

  def_delegator :opportunity, :organization, :opporunity_organization


You can use open to open a file, or (if you require open-uri) you can grab stuff off the net:

sample = open("") do |f|

You can also use open to send all the output of your program through less:

open("|less", "w") do |f|
  80.times do |i|
    f.puts "Line #{i}"

Here's a neat trick; use a pager if your program is used interactively:

if STDOUT.tty?
  $stdout = open("|less", "w")

# send stuff to STDOUT


Array#assoc and rassoc

These methods are handy for looking up stuff inside nested data structures:

data = [["cat", "kitten", "feline"],
        ["dog", "puppy", "caine"],
        ["bear", "cub", "ursine"]]

data.assoc("dog") # -> ["dog", "puppy", "caine"]
data.rassoc("kitten") # -> ["cat", "kitten", "feline"]


unpack works on a string. You can do really clever stuff, such as reading a QT/MPEG4 atom header:

length, name ="Na4")

"N" means that you should read 4 bytes in big endian order. "a" Means you should read ascii text. 4 means you should read 4 of thing represented by the previous character.

You can pack it all back up again to produce binary output:

header = [1234, "moov"].pack("Na4")

You can also do unicode:

codepoints = "string".unpack("U*")
=> [115, 116, 114, 105, 110, 103]

The asterisk means "any number of", so you get any number of code points back from your string.

So if you know a code point you can get the right character, without knowing how to type it on your keyboard:

em_dash = [0x2014].pack("U")  # emdash, apparently


A set only keeps one copy of everything that you put in it, so it's a great way to track unique items. I liked this code for finding the set of vowel sequences that occur in a list of words:

Finding sequences with Ruby

This should come as no surprise, but you can also run set operations on your set objects:

require "set"

a =[:a, :b, :c])
b =[:a, :b])

a | b  # union of the two sets
a & b  # intersection (i.e. which items occur in both)

Soap (yuk)

If you have to do SOAP you want to do it in a way that makes it as easy as possible. It's pretty straightforward with the soap/wsdlDriver in the standard library.


pp stands for "pretty print". It's a nice way to get a clean dump of a data structure in irb.

Cool stuff. I need to spend some time getting my head around pack/unpack...

More talks from Ruby Manor