Hash and Array #dig
When dealing with nested JSON-like data, code tends to get noisy real fast. Given the world we live in where JSON is the de facto serialization format for web APIs, let's see how the dig method can help us out when dealing with it.
payload = {
"order" => {
"customer" => { "address" => { "country" => "SE" } },
"line_items" => [{ "sku" => "RB-001" }]
}
}
country = payload.dig("order", "customer", "address", "country")
# => "SE"
first_sku = payload.dig("order", "line_items", 0, "sku")
# => "RB-001"
coupon = payload.dig("order", "discount", "code") || "NO-CODE"
# => "NO-CODE"
const payload = {
order: {
customer: { address: { country: 'SE' } },
line_items: [{ sku: 'RB-001' }]
}
};
const country = payload?.order?.customer?.address?.country;
// => 'SE'
const firstSku = payload?.order?.line_items?.[0]?.sku;
// => 'RB-001'
const coupon = payload?.order?.discount?.code ?? 'NO-CODE';
// => 'NO-CODE'
When missing data should be an error instead of nil, fetch still has our back. But for tolerant reads, dig keeps things relatively clean.
A dig I wish I had
Though I frequently use .dig in my IRB sessions, I don't always love using it in production code.
I tend to lean towards "confident" programming. That is, I prefer to write code that assumes the data is in the expected shape and lets it raise an error if it's not.
In those cases, I wish there was a dig that would raise an error if any part of the path is missing, as an alternative to chaining a bunch of .fetch calls together.
Perhaps someone listening out there could be tempted to open a pull request to add dig! to ActiveSupport or something? 🙏😇
History
Hash#dig and Array#dig were added in Ruby 2.3.0, released on Christmas 2015.