Debugging
What are you going to learn?
- Understand how to read error messages
- How to use Pry as a debugger tool to create breakpoints
Debug
The process of debugging code, is something that we as developers do all the time not matter how experience you are. The main reasons to debug are:
- The program does not run, and there is an Error
- The code runs, but you are not getting what is expected. Failure or Bug
A software bug is an error, flaw or fault in a computer program or system that causes it to produce an incorrect or unexpected result, or to behave in unintended ways
Having a debugging process or capability allows us to identify with ease the errors or bugs we introduce to the code. A simple 4-step process would look like:
- Read the whole error
- Find the error, commonly Ruby gives you the file and line number causing the error
- Establish a hypothesis
- Try your hypothesis
Pry
A common tool to use for debugging is a gem called Pry. This gem allows us to add breakpoints in our code inspect values from variables or the state of an object.
To start using this gem, you can simply install by:
$ gem install pry
And then on your script, you need to require the gem like so:
require 'pry'
Adding a breakpoint
In order to add a breakpoint anywhere in our code, just add the following line:
binding.pry
Check the code below for a complete example:
fruits = ["apple", "banana", "watermelon", "peach"] fruits.each do |fruit| binding.pry puts fruit.upcase end
The code above, will stop 1 time per fruit on the array, and on each iteration we will be able to access the fruit
variable or any other if that would be the case.
Stack trace
Ruby is usually friendly when it comes to output errors into the console or what is called the stack trace. This is how it looks like when trying to run this code:
class SuperHeroe def initialize(name) @name = name end def greetings "Hi, my name is #{self.name}" end end super_heroe = SuperHeroe.new("SpiderMan") super_heroe.greetings
The output after running this would be:
Traceback (most recent call last): 1: from super_heroe.rb:12:in `<main>' super_heroe.rb:7:in `greetings': undefined method `name' for #<SuperHeroe:0x00005597eea2dab0 @name="SpiderMan"> (NoMethodError)
Let's break this down a little bit:
- As you can see the first line - "1: from super_heroe.rb:12:in
<main>'" is telling us the error was triggered by the line 12, in this case the invokation for the
greetingsmethod on the
super_hero` variable. -
Then, if we keep reading, the actual error is happening on line
7
from the file. The line readssuper_heroe.rb:7:in 'greetings': undefined method 'name' for #<SuperHeroe:0x00005597eea2dab0 @name="SpiderMan"> (NoMethodError)
.- As you can see, Ruby is telling us that the
name
method does not exists for the current instance. And all of this happened while trying to run thegreetings
method.
- As you can see, Ruby is telling us that the
The trace would look something like:
SuperHero.new -> #greetings -> #name
One alternative to fix the code above, is to add the method name
:
class SuperHeroe attr_reader :name def initialize(name) @name = name end def greetings "Hi, my name is #{self.name}" end end super_heroe = SuperHeroe.new("SpiderMan") super_heroe.greetings