Jon Simpson

Named Arguments Not Passed Correctly via Hash in Ruby 2.2.2

20 Jul 2015 — ruby, bug

Encountered this weird edge-case bug when using a hash to pass required named keyword arguments in Ruby and using the double splat operator (**), which allows additional keys to be present in the hash rather than just the expected parameters.

The hash had the correct keys and values before being passed into the method, but once passed all keys after the second were empty or “1” instead of having the values of the matching hash keys.

Reading Trollop’s parse method and much trial and error it turns out that some symbols acting as keys in the hash were being converted to symbols from strings. There’s a bug in a number of versions of Ruby, including Ruby 2.2.2p95 (Bug #11091 Symbolized Strings May Break Keyword Arguments) which covers corruption of the symbol table in this case.

A minimal example of the problem is below; as soon as the hash contains a symbol key which has been converted from a string, the keyword argument values can’t be retrieved from the hash. Hopefully this saves someone else a few hours of debugging.

def test (first:, second:, **extra)
  puts "First: #{first}, Second: #{second}"

hash = {first: "value1", second: "value2"}
# Output: First: value1, Second: value2

hash["third".to_sym] = "value3"
puts hash
# Output: {:first=>"value1", :second=>"value2", :third=>"value3"}

# Output: First: value1, Second: