My favorite class in all of our API

David Pedersen
Tonsser
Published in
2 min readSep 14, 2016

--

At Tonsser our backend API is a Ruby on Rails app that primarily renders JSON. We’ve been doing TDD since day one, and currently have almost 1800 tests, so you can probably imagine we’re calling Hash#[] all over the place in our integration tests.

Here is what a typical test might look like:

describe "GET /users/:slug" do
it "returns the user’s first and last name" do
bob = create :user, firstname: "Bob", lastname: "Johnson"
get "/users/#{bob.slug}"
json = JSON.parse(response.body)
expect(json[:response][:firstname]).to eq bob.firstname
expect(json[:response][:lastname]).to eq bob.lastname
end
end

This test is fine but the code could be cleaner. Two things will quickly become tedious:

  1. Manually parsing the response body into a Hash.
  2. Accessing the properties of the JSON requires more typing than necessary.

The first problem is easily fixed. We just extract a method like this:

def json
JSON.parse(response.body)
end

To solve the second issue we’ve written a class called HashWithQuickAccess. Is is probably my favorite class in the whole code base. Using it changes this:

json[:response][:firstname]

Into this:

quick_hash = HashWithQuickAccess.new(json)
quick_hash.response.firstname

And it doesn’t just stop there. It also handles arrays within the hash and allows you to write something like:

quick_hash.response.teams.flat_map(&:users).first.slug

Without using HashWithQuickAccess that would be really ugly:

json[:response][:teams].flat_map { |team| team[:users] }.first[:slug]

The test from above is now much nicer:

describe "GET /users/:slug" do
it "returns the user's first and last name" do
bob = create :user, firstname: "Bob", lastname: "Johnson"
get "/users/#{bob.slug}" expect(json.response.firstname).to eq bob.firstname
expect(json.response.lastname).to eq bob.lastname
end
end

We like HashWithQuickAccess so much (and wanted to use it in other projects) that we extracted it into a gem called tonsser-hash-utils. It also includes a few other utility classes for working with hashes but HashWithQuickAccess is by far the one we use the most.

If your app deals with lots of JSON we encourage you check out the gem.

--

--

David Pedersen
Tonsser

Developer at @tonsser, computer science student, martial artist, addicted to Cardistry