Today I Learned

hashrocket A Hashrocket project

Variable Hoisting in Ruby

This afternoon my pair and I spent quite a while on a subtle bug. The culprit? Variable hoisting.

Take this file:

class Test
  def self.hoist
    require 'pry'; binding.pry;
    bar = 1
  end
end

Test.hoist

When we hit the PRY debugger, what will the value of bar be? I would have thought it would raise NameError, because bar has seemingly not yet been defined.

Wrong:

$ ruby test.rb

From: /test.rb @ line 4 Test.hoist:

    2: def self.hoist
    3:   require 'pry'; binding.pry;
 => 4:   bar = 1
    5: end

[1] pry(Test)> bar
=> nil

When Ruby parses a file, it 'hoists' each variable to the top of its scope, declaring and setting it to nil, even if that variable is never assigned by our code. So variables inside an if false conditional get hoisted and set to nil, as described in this blog post.

This is can be a real gotcha.

h/t Jack Christensen

See More #ruby TILs
Looking for help? Each developer at Hashrocket has years of experience working with Ruby applications of all types and sizes. We're an active presence at Ruby conferences, have written some of the most popular gems, and have worked on many of the web's Ruby on Rails success stories. Contact us today to talk about your Ruby project.