Debugging Tips

How to debug your Ruby scripts without losing your hair over it.

Scroll down...

Content

Resources

Comments

You'll spend a LOT of time debugging your code. If you've followed the higher level concepts we introduced over the past few lessons (especially about using many small methods and classes), then you're in a good position to quickly debug the code. Even so, following a good debugging approach will help you save a lot of time in the long run.

In this very brief lesson, we'll lay out a debugging approach and introduce you to a few tools which can make your life easier. In particular, we'll show you the Pry REPL which should replace IRB as your favorite command line tool. The further along we get, the more useful Pry will become, so best start getting used to it now!

The Approach

  1. Actually read your error message. It'll provide context like the line number and the stack trace. Google the message if you need to in order to understand it.
  2. Think through where it could be coming from in your code. Form a hypothesis.
  3. Try out your hypothesis. Were you right?
  4. Step through the debugger (using a binding.pry) if you need more backup.

A Vanilla Debugger: Byebug

There's a gem called byebug which lets you pause your code execution in the middle so you can manually step through it to see what might be wrong. We won't dive deeply into it but it's a useful tool to get accustomed to on your own because you no longer need to run your code in your head -- Byebug keeps track of everything for you.

You'll find debuggers similar to this regardless of which language you pick up. They're that useful. In fact, we'll cover the very similar pry debugger in just a sec which we recommend over just plain byebug.

To use the vanilla byebug gem, simply install the gem, include it in your code, and then run it at the specific point where you think the failure might be by using the byebug method:

# CLI
$ gem install byebug

# my_script2.rb
require 'byebug'

def buggy
  byebug    #<<<<<<<< where byebug will stop the first time
  puts "I'm a buggy method!"
  [1,2,5,0,1].each do |num|
    1000/num
  end
end

# IRB
 > load 'my_script2.rb'
 => true 
 > buggy

[1, 9] in my_script2.rb
   1: require 'byebug'
   2: 
   3: def buggy
   4:   byebug
=> 5:   puts "I'm a buggy method!"
   6:   [1,2,5,0,1].each do |num|
   7:     1000/num
   8:   end
   9: end

(byebug):    # <<< this is the command prompt

When you run byebug, you'll jump into a REPL (live interactive code) session just like IRB. You can then step piece-by-piece through your code and investigate what variables are at every point along the way.

Read the documentation on Github for basic instructions or the how-to Guide for more details.

Helpful commands:

  • step steps you one additional increment through the program
  • Pressing ENTER will continue the last command (e.g. step)
  • p followed by a variable name will print the value of that variable
  • quit/q/exit leave Byebug.

Note: Byebug only works for Ruby 2.x. If you're using Ruby 1.9.x, use the debugger gem instead

We'll leave it up to you to experiment with this particular gem, though we recommend you actually use the very similar Pry Debugger.

A Better Debugger and REPL: Pry

You've probably been using IRB as your REPL of choice so far just because it comes with Ruby. IRB is pretty nuts and bolts -- it gets the job done well and that's about it. It's dry and functional, just like the command line should be...

Pry is a different story. It has all the features of IRB plus all kinds of useful bells and whistles that will make your life MUCH easier. It's a free gem that's easy to download and use and, as you'll see later, it's got some really powerful features and extensions. And it's colorful!

Installing Pry

Pry is a gem like any other:

$ gem install pry

To use it, just type pry into the command line instead of irb:

$ pry
>       # start REPL-ing!

Debugging with Pry

Remember the byebug gem from about 30 seconds ago? Pry natively gives you very similar functionality and the commands are pretty much identical. If you miss some of the extra commands that Byebug has, there's a pry-byebug gem which does exactly the same thing for Pry.

We recommend you use Pry (via binding.pry statements) to debug instead of running the Byebug debugger in IRB.

To debug with Pry, you can add a binding.pry statement in the middle of your code and it will cause the Ruby script to jump into Pry just like you saw above with Byebug. The syntax for this is the same as with Byebug. You can inspect variables as if you're in the middle of a normal Pry or IRB session.

The most common reason for doing this is to verify the state of your program when a certain point has been reached.

For example, you might have the attack method of your Viking running but nothing actually seems to happen. So you can put the binding.pry line at the top of the method and inspect your script's state from that exact point. You might realize that, oops, the @weapon variable is set to nil so you aren't actually doing any damage. You forgot to pick up a weapon first!

require 'pry'

class Viking
  ...
  def attack(recipient)
    binding.pry
    ...
  end
end

Other Useful Features

Here are a few other useful features of Pry which you can consider supplementary. You don't need to go out and learn the whole scope of the gem right off the bat -- it's best to get used to it first and then gradually start picking up new tricks. The Pry Documentation is a useful place to pick up new tricks and some creative Googling will reveal the rest.

Tips

  • Make liberal use of inspect statements to save some time when checking out variables. For instance, try self.inspect to see the state of the current binding.
  • If you're stuck in an infinite or very long loop (e.g. you put binding.pry in a while loop), even typing quit in Pry will just jump to the next binding.pry statement. To fully quit the script, type exit-program or !!!.
  • Go install and use Pry!!!


Sign up to track your progress for free

There are ( ) additional resources for this lesson. Check them out!

There are no additional resources for this lesson just yet!

Sorry, comments aren't active just yet!

Next Lesson: Procedural Ruby