Skip to content
Open
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 182 additions & 4 deletions ruby/basic_ruby/debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,188 @@ As you can see, using Pry-byebug for debugging achieves the same outcome as `put

There is far, far more that you can do with Pry-byebug, but that's beyond the scope of this lesson. Check out the Assignments and Additional Resources to find out where you can learn more about this useful gem.

### Debugging with vscode-rdbg

#### Step 1: Installation

1. Go to your [VSCode Extensions](https://code.visualstudio.com/docs/editor/extension-marketplace) and install the [Ruby LSP](https://marketplace.visualstudio.com/items?itemName=Shopify.ruby-lsp) extension. This is a LSP(Language Server Protocol) which gives you autocompletion as you type ruby code in editor and much more amazing stuff.
Comment thread
XAJX179 marked this conversation as resolved.
Outdated

1. Before installing `vscode-rdbg` extension let's fulfill it's requirements first.
Comment thread
XAJX179 marked this conversation as resolved.
Outdated
You need to install latest `debug` gem and `rdbg` command should be in `$PATH` environment variable. A command in `$PATH` can be called from any directory.
Comment thread
XAJX179 marked this conversation as resolved.
Outdated

```shell
gem install debug
```

```shell
which rdbg
# /home/yourusernamehere/.rbenv/shims/rdbg
```

If you don't see path output like the comment above ask for help in our [Discord community](https://discord.gg/fbFCkYabZB).

1. Now install the [VSCode rdbg Ruby Debugger](https://marketplace.visualstudio.com/items?itemName=KoichiSasada.vscode-rdbg) extension.

#### Step 2: Setup

1. Set version manager.

1. Open VScode.
1. Press <kbd>Ctrl</kbd> + <kbd>,</kbd> to open settings.
1. Search "rdbg ruby version manager".
1. Set it to `rbenv` which we made you install in [installing ruby lesson](https://www.theodinproject.com/lessons/ruby-installing-ruby#step-21-install-rbenv) , it's your version manager for ruby : [rbenv documentation](https://github.com/rbenv/rbenv).
Comment thread
XAJX179 marked this conversation as resolved.
Outdated
1. Search "ruby lsp version manager"
1. Click on the 'Edit in settings.json' link
Comment thread
XAJX179 marked this conversation as resolved.
Outdated
1. Edit the identifier which is by default "auto" to "rbenv"
Comment thread
XAJX179 marked this conversation as resolved.
Outdated

1. Confirm settings.json have these two configurations set correctly:

```json
{
"rdbg.rubyVersionManager": "rbenv",
"rubyLsp.rubyVersionManager": {
"identifier": "rbenv"
},
}
```

#### Step 3: Get some bugs

Let's Add Some code files for demo:

1. Go to Desktop `cd ~/Desktop/` and create a new folder `mkdir dummy_name`.
1. Open the folder in vscode `code dummy_name/`
1. Create new file `main.rb` inside `dummy_name/` and copy the following code containing some bugs:

```ruby
# check if password is correct
def check_password(input)
password = 'xajxwashere'
if input = password
puts "Access granted!"
else
puts "Wrong password."
end
end

def start_password_input
puts "Enter a password:"
input = gets.chomp
puts "result : #{check_password(input)}"
end

# give day name of the given day number
def day_name(num)
days = %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday]
if num >= 1 && num <= 7
days[num]
else
"Invalid"
end
end

def start_day_name_input
puts "Enter day number (1–7):"
n = gets.to_i
puts "Day is #{day_name(n)}"
end
```

1. Create another file `not_main.rb` inside `dummy_name/` and copy the following code into `not_main.rb` :

```ruby
puts "Sup Odin Student"

def message_number(index)
index + 1
end

5.times do |index|
num = message_number(index)
puts "message number: #{num}"
end
```

#### Step 4: Create launch.json

1. Press <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>D</kbd> to go to `Run And Debug` inside vscode.
1. Click 'create a launch.json file.' This file is used to configure our debugger.
1. Select `Ruby (rdbg)` option on the pop-up menu.
1. Close the 'launch.json' file tab and confirm that it's saved at this place `dummy_name/.vscode/launch.json`:
![Sample stack trace](https://cdn.statically.io/gh/TheOdinProject/curriculum/a2cfa47e944fa8127ccf5faa6e1c7c328de42428/ruby/basic_ruby/debugging/imgs/00.png)

#### Step 5: Run Debugger

1. Open `not_main.rb` file and press <kbd>F5</kbd> OR on the menu bar click `Run` and inside it `Start Debugging`. By default the file currently opened will be used to start debugging, you will see a pop-up with command running the current file since we don't wanna pass any parameter to `rdbg` just press enter. (You can also set `askParameters` inside the `launch.json` to `false` which will skip this pop-up.)
1. You can toggle the `Debug Console Output` using <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>Y</kbd>.
1. Confirm the code outputs inside `Debug Console Output` like this:
![Sample stack trace](https://cdn.statically.io/gh/TheOdinProject/curriculum/a2cfa47e944fa8127ccf5faa6e1c7c328de42428/ruby/basic_ruby/debugging/imgs/00.png)
1. Move your mouse pointer to the left side of line number 7 and then left click to add a breakpoint:
![Sample stack trace](https://cdn.statically.io/gh/TheOdinProject/curriculum/a2cfa47e944fa8127ccf5faa6e1c7c328de42428/ruby/basic_ruby/debugging/imgs/00.png)
1. Run Debugger again by pressing <kbd>F5</kbd>, the debugger will stop program on our breakpoint and give us some debugging actions to use.
Comment thread
XAJX179 marked this conversation as resolved.
Outdated
![Sample stack trace](https://cdn.statically.io/gh/TheOdinProject/curriculum/a2cfa47e944fa8127ccf5faa6e1c7c328de42428/ruby/basic_ruby/debugging/imgs/00.png)
1. Read details of the commonly used debugging actions:

| Action | Description |
|:--|:--|
| Continue / Pause <kbd>F5</kbd> | **Continue**: Resume normal program/script execution (up to the next breakpoint). **Pause**: Inspect code executing at the current line and debug line-by-line. (for short and fast programs you might not get the chance to pause quickly and code will execute fully) |
| Step Over <kbd>F10</kbd> | Execute the next method as a single command without inspecting or following its component steps. |
| Step Into <kbd>F11</kbd> | Enter the next method to follow its execution line-by-line. |
| Step Out <kbd>Shift</kbd> + <kbd>F11</kbd> | When inside a method or subroutine, return to the earlier execution context by completing remaining lines of the current method as though it were a single command. |
| Restart <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>F5</kbd> | Terminate the current program execution and start debugging again using the current run configuration. |
| Stop <kbd>Shift</kbd> + <kbd>F5</kbd> | Terminate the current program execution. |

1. While watching local variables in the `VARIABLES` window of `Run And Debug` which is by default on the left side and also keeping `Debug Console Output` opened, keep pressing <kbd>F11</kbd> OR `Step Into` button and follow the code execution line-by-line, this file was only for introduction there are no bugs in it so start reading next step.

#### Step 6: Debug some code

1. Open `main.rb` and press <kbd>F5</kbd> to start debugger, notice the debugger disconnected immediately without running any code.
1. This is because currently the `main.rb` file is only defining methods using the `def method_name ... end` syntax but no method is being called in this file, so let's call a method:

Add this at the end of file to call `start_password_input` method:

```ruby
# calling the method
start_password_input
```

1. Put a breakpoint on method call and press <kbd>F5</kbd> to start debugger, When you keep stepping into you will notice in the `Debug Console Output` the program will ask you for user input, but there's a problem you can't enter any input here.
1. If your program needs user input we have to use `Terminal` instead of `Debug Console Output` so we can enter input while debugging, for that we have to configure our debugger so open `launch.json` at `dummy_name/.vscode/launch.json` and add `"useTerminal": true` at end of config named `Debug current file with rdbg` like this:

```json
{
"type": "rdbg",
"name": "Debug current file with rdbg",
"request": "launch",
"script": "${file}",
"args": [],
"askParameters": true,
"useTerminal": true
},
```

1. Open `main.rb` and put a breakpoint on method call (if there isn't already), press <kbd>F5</kbd> to start debugging.
1. Keep Stepping Into till you hit the user input line (`Step Into` one more time if you see still yellow background on the gets.chomp line), open `Terminal` (if it's not opened already) using <kbd>Ctrl</kbd> + <kbd>`</kbd> and enter any input inside the "Ruby Debug Terminal".
1. You can now debug while giving user input in between, keep stepping into till you reach the `if` condition, `Step Into` one time and notice the flow. It passed the condition and went inside if condition and in local variables we see that `input` variable got assigned the value of `password` variable, instead of comparing it with that value. Can you guess the fix? Drop your answer in [TOP Discord's #ruby-rails-general channel](https://discord.com/channels/505093832157691914/690591236922409012).
Comment thread
XAJX179 marked this conversation as resolved.
Outdated

#### Step 7: Debug some more code

1. Open `main.rb` and comment out `start_password_input` method call and add `start_day_name_input` at end of file :
Comment thread
XAJX179 marked this conversation as resolved.
Outdated

```ruby
# start_password_input
start_day_name_input
```

1. Run the debugger and on user input enter "7".
1. Notice the output is only "Days is" and no name after it.
1. Put a breakpoint on the method call if there isn't already, run the debugger and on user input enter "7" again.
Comment thread
XAJX179 marked this conversation as resolved.
Outdated
1. Keep Stepping into till the `if` condition line and press `Step Into` one more time.
1. Notice how the condition passes meaning 7 is valid input, so problem is `days[num]`.
Comment thread
XAJX179 marked this conversation as resolved.
Outdated
1. On `WATCH` window of `Run And Debug` inside vscode click add expression(the plus icon) and add `days[num]`, and you will see the value returned by `days[num]` is nil. (use mouse to hover over `WATCH` to get "add expression" button)
Comment thread
XAJX179 marked this conversation as resolved.
Outdated
1. Add `days` and `num` to `WATCH` too, click on `days` to expand it and notice the array index starts with 0 and ends at 6 and currently the `num` 7 is out of range.
Comment thread
XAJX179 marked this conversation as resolved.
Outdated
1. The `WATCH` section can evaluate expressions and it's helpful when the local variable you want to check is deeply nested when checking inside local variable of `VARIABLES` window, let's try some expressions inside `WATCH` to figure out some working code for the `days[num]` bug. Add `days[num+1]` and `days[num-1]` to `WATCH` , local variables will show you just the current value of a variable and using `WATCH` expressions you can play with your variables and check the value of conditions like `num >= 1 && num <= 7`, add this condition to `WATCH` and it will show `true` if `num` is greater than 0 and smaller than 8 else false. Notice the fix for this bug is using `days[num-1]` since allowed inputs are 1-7 and array index are 0-6.
Comment thread
XAJX179 marked this conversation as resolved.
Outdated

### How to start debugging

Programs generally go wrong due to two main reasons:
Expand All @@ -207,10 +389,6 @@ Obviously, if available, <span id='debugging-with-stack-trace'>the stack trace i

1. Go through the Ruby Guides [Ruby Debugging](https://www.rubyguides.com/2015/07/ruby-debugging/) tutorial, which covers the same topics we went over, but in more depth.
1. Read through the [Exceptions and Stack Traces](https://launchschool.com/books/ruby/read/more_stuff#readingstacktraces) section of Launch School's online book *Introduction to Programming with Ruby*.
1. Check your [VSCode Extensions](https://code.visualstudio.com/docs/editor/extension-marketplace) and make sure the [Ruby LSP](https://marketplace.visualstudio.com/items?itemName=Shopify.ruby-lsp) and the [VSCode rdbg Ruby Debugger](https://marketplace.visualstudio.com/items?itemName=KoichiSasada.vscode-rdbg) extensions are installed.
1. Now that you're familiar with the basics, we're going to have some fun with VSCode! Check the [VSCode rdbg Ruby Debugger documentation](https://github.com/ruby/vscode-rdbg) and generate the configuration inside your VSCode by going to `Run and Debug` and clicking on `create a launch.json file` then picking `Ruby (rdbg)`. Now, the configuration you want to use is `Debug current file with rdbg` that you can see at the top of the Debug sidebar. You can also invoke the last used debugging configuration with `F5`. `launch.json` files need to be created on a per project basis. If you're having a hard time figuring out how to navigate to your `launch.json` file in order to change the configuration, peek into [Debugging with VScode launch configurations portion](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations). We encourage you to go through the entire article, though!
1. Now that everything is installed, configured, let's create a new file which you can call `script.rb`. Next copy and paste the very first example in the [Debugging with pry-byebug](#debugging-with-pry-byebug) Section. Get rid of the `require pry-byebug` line and change `binding.pry` to `debugger`. Save the file.
1. Click the `Run and Debug` button, open up the folder your script is located in, set a VSCode breakpoint somewhere within the function, and Run the debugger! This should all look very familiar to you, when you hit the VSCode breakpoint it should look similar to the breakpoints you used in the [JavaScript Developer Tools lesson](https://www.theodinproject.com/lessons/foundations-javascript-developer-tools). But *whoa*, once we hit the `debugger` breakpoint we got an interactive REPL to play around with! The best of both worlds! Play around with this, and feel free to reference [Debugging with VScode documentation](https://code.visualstudio.com/docs/editor/debugging) if you get stuck.
1. Although VSCode's debugger is a helpful tool that can make debugging simpler, many companies won't be using it - and will want you to be familiar with debugging using the concepts this lesson focused on: the stack trace, `puts`,`debug`, `pry-byebug`. Let's practice them by completing the debugging exercises from the [ruby-exercises repo](https://github.com/TheOdinProject/ruby-exercises/tree/main/ruby_basics#readme) that you previously cloned.

</div>
Expand Down
Loading