Avoiding nil errors

Here is a quick way to avoid nil errors and get better failures in Ruby and Ruby on Rails. Convert hashes with known keys into Structs: data = { a: 1, b: 2, c: 3} ... MyData = Struct.new(:a,:b,:c) data = MyData.new(a: 1, b: 2, c: 3) Structs will throw if you introduce a typo instead of returning nil. This tightens your feedback loops and reduces debugging time. hash[:d] => nil struct[:d] => in 'Struct#[]': no member 'd' in struct (NameError) That is cool. What about in more fluid situations like user input? You can convert arbitrary incoming hashes into known structs quickly with the following: params = {a: 1, b: 2, c: 3, x: 9, z: 0} MyData.new(**params.slice(*MyData.members)) Pitfalls While Structs have much the same interface as hashes, there are some tricky differences. Hash#each is equivalent to Struct#each_pair. Hash#keys is equivalent to Struct#members. There is no equivalent to Hash#fetch.

May 16, 2025 - 03:06
 0
Avoiding nil errors

Here is a quick way to avoid nil errors and get better failures in Ruby and Ruby on Rails. Convert hashes with known keys into Structs:

data = { a: 1, b: 2, c: 3}
...
MyData = Struct.new(:a,:b,:c)
data = MyData.new(a: 1, b: 2, c: 3)

Structs will throw if you introduce a typo instead of returning nil. This tightens your feedback loops and reduces debugging time.

hash[:d] => nil
struct[:d] => in 'Struct#[]': no member 'd' in struct (NameError)

That is cool. What about in more fluid situations like user input? You can convert arbitrary incoming hashes into known structs quickly with the following:

params = {a: 1, b: 2, c: 3, x: 9, z: 0}
MyData.new(**params.slice(*MyData.members))

Pitfalls

While Structs have much the same interface as hashes, there are some tricky differences.

  • Hash#each is equivalent to Struct#each_pair.
  • Hash#keys is equivalent to Struct#members.
  • There is no equivalent to Hash#fetch.