From the cool_shit file

Origins

For the last 8ish years I’ve had a file on my computer named “cool_shit”. I started it at one Seattle.rb meeting when Ryan Davis and Eric Hodel were teaching me new thing after new thing and I was pretty sure I couldn’t remember them all. It is essentially my coding scrapbook/snippets repository. When I started working at Substantial my work computer got a “cool_shit” file as well. Six months ago I realized, “hey I’m no longer a newb, maybe I should organize this better” and the “cool_shit” file became the “resources” directory which contains a few org files and a handful of ruby files.

What goes in the resources directory? The stuff that I won’t memorize but is occasionally exactly what you need. Things like example ruby classes, steps for creating a gem, and shell commands you use once or twice a year. For example, the first entry was between? on comparables. each_slice went in there after the first Cascadia Ruby Conf.

Here are couple ruby specific things in my resources directory:

Hash of Arrays

I know a lot of folks (myself included) got thwarted the first time they tried to make a hash of arrays. Usually because they tried something like this:

1
Hash.new []

If you’ve never passed an arg to Hash::new go try this in irb. Then realize it doesn’t work. It doesn’t work because all of your hash entries are sharing the same default value. As in, they are sharing the same instance of Array.

The correct way is this:

1
Hash.new { |h, k| h[k] = [] }

The block form of Hash::new executes the block (with the hash and the key) each time you try to access a key that isn’t in the hash. This means each key gets a new instance of Array which is probably what you wanted in the first place.

HashHash

Sometimes you want nested hashes all the way down. Ryan Davis gave me this example. I don’t need it often but when I do I’m glad I don’t have to remember about how to do it.

1
2
3
4
5
class HashHash < Hash
  def initialize
    super { |h,k| h[k] = HashHash.new }
  end
end

rescue nil

One of the first things I learned from the folks at Seattle.rb is that .nil? is a code smell. You can almost always design your code so that you don’t need it. Usually I use things like a postfix if: m = x.max if x. But if I’m trying things out or refactoring some poorly written ruby the following is quite handy.

1
x = stuff.that.you.actually.want.to.do rescue nil

Yes, there are other ways to do this in 1.9 and 2.0. Everything in today’s post comes from the time of Ruby 1.8.5. If you like the new ways use them. Ruby has lots of ways to do common things.

I use rescue nil when debugging import/parsing scripts for files that aren’t well formed. I’ve also used it when refactoring some particularily Java like ruby that had nil? spread all over the place. Once I had the nil checks removed and could tell what values were actually requried it was easier to restructure the code to something more understandable and maintainable.

[my_obj.methods - Object.methods].sort

The last trick for today is one I saw Ryan do at the first Seattle Rails Bridge. Someone asked what types of methods were available on an instance of Array. Ryan was already in irb and typed this:

1
[my_obj.methods - Object.methods].sort

I use this ALL THE TIME. I know this same information is available in the documentation but sometimes I’m in irb (or pry) and can’t be bothered to go look up something in docs. And sometimes there aren’t any docs or the docs are out of date.

I mostly do this when trying out a new gem in irb. I’ll be following a tutorial and I’ll have an object that probably does what I want. So I look at the methods to see what it can do. This technique is also great for revealing intent. If an object has methods for status and body it is probably wrapping up an HTTP response. If it has each the author intended it to be an enumerable. I’ve worked with some services that return objects with classes like TagCollection. Seeing that the methods include each and reverse lets me know that this is probably delegating to an array and I should treat it as such.