00:00:10.160
Hi everybody, thank you for your warm welcome. I would like to thank all the organizers of this day. They have done a great job, and it is truly a pleasure and an honor to be here. So, thank you for all the time you have spent on this event. My name is Enrico Carlesso, and I have been a software developer for the past 10 years. I must admit that I am not an experienced speaker, so I apologize in advance for that.
00:00:33.879
You might ask why I am giving this talk. When I found out it was Ruby Day, I reflected on what has really changed my life when it comes to working in Ruby. Even though I don't particularly enjoy speaking in public, I would like to share with you the tool that has dramatically changed the way I work and has saved me a significant amount of time.
00:01:07.200
Just a brief mention about the company I work for, named Codor 51, which is based in Bologna. I've been working with them for the past two years. Unfortunately, our journey together has come to an end, but it has been a great pleasure to work with you all.
00:01:48.520
The topic of debugging is quite interesting, especially since this talk follows one from Kristoff, as our discussions share a lot of common ground. As Kristoff mentioned, we often spend much more time reading code than writing it. This is primarily because we are continuously debugging our code. You write something, unsure if it will work. You might be working on someone else's code, and in those cases, you often don't know what you're doing. This makes the process of reading and understanding your code a lengthy one.
00:02:16.440
Typically, the debugging process goes like this: you need to find an exception and hope you have the stack trace. If you don't know how to use the trace course gem from Kristoff, you might end up relying solely on the stack trace. You open your editor, search for the relevant line, start adding some puts statements to check values, and then try running the code again. For many languages that are not scripted, this process often involves seeing thousands of outputs. With Ruby, however, you usually don't need to compile; instead, you just check the output and make some changes, hoping for a positive result.
00:02:46.000
If you are very lucky, you might solve the bug and move on—though, oftentimes, you find yourself frustrated by time-wasting bugs. This is especially true when working in corporate environments where you might be dealing with software that is not open source. The developers may not strive to keep the code well-organized as they would in open-source projects, so you often find a mess of issues scattered throughout the code.
00:03:10.159
As a Rubyist, you know that Ruby is a scripting language that does not require compilation. It runs exactly as written, enabling a great degree of introspection and reflection. This means you can check live objects when working with them and inspect the running program. Ruby excels in metaprogramming, which opens the door for alternatives like Pry.
00:03:42.840
I apologize if I call it 'pre' instead of 'pry,' as we tend to use 'pre' in Italy. Pry serves as a powerful alternative to the standard IRB for Ruby users. How many of you use Ruby on Rails? And how many of you use Ruby without Rails? Most of the time, when you open IRB, it's the default Ruby console where you can play around with the code. Pry offers a powerful alternative to IRB, with features like syntax highlighting, a flexible plugin architecture, and runtime invocation.
00:05:15.520
Pry is an acronym that stands for 'Read-Eval-Print Loop.' The simplest possible REPL in Ruby started with just 75 lines of code. Essentially, it allows you to read a line of code, evaluate it, and print the output. This loop is what makes Pry so outstanding compared to IRB and other alternatives.
00:05:48.000
Pry comes with many useful features such as syntax highlighting and tab completion, which is hugely beneficial for those of us who can be a bit lazy with typing. One impressive feature is the underscore and double underscore, which allow you to access the last outputs directly within Pry. It significantly changes the way I debug or try to fix code.
00:06:22.240
Inside the Pry console, you can view the documentation for a method or class, and most importantly, you can check the source of a specific method. More often than not, we use methods or objects that reside in our projects, and they often aren't documented because many developers may overlook documentation, hoping that Ruby's self-explanatory nature will suffice. The command 'ls' allows you to list all local variables in your current context. The 'cd' command is another fascinating feature that lets you navigate as you would in a Unix system, moving into objects instead of directories.
00:07:00.039
For instance, if you have an instance of a User model, you can 'cd' into that object and access all its methods directly. This means you can call private methods without needing tedious workarounds. Another excellent feature is the 'edit' command, which opens your preferred editor directly in the file of the specified method or class.
00:07:42.080
The binding.pry command is significant because it allows you to pause execution at a specific point in your Ruby code and access all the context around it. You can put this single line anywhere in your Ruby file or Rails application, and when your code executes that line, it will open a Pry shell right there.
00:08:23.760
This capability gives you access to real data flowing through your application, which is incredibly valuable for understanding what is happening during execution. For example, if you have a Rails controller behaving strangely, you can simply add 'binding.pry,' refresh your browser, and the console will allow you to inspect the data flowing through that controller at that exact moment.
00:09:01.960
Why is this important? Well, when you open the Pry console at that line, you can access all the variables in that exact call. If you remove the binding.pry command, your application will continue to run as normal. This lets you view the actual, real-time data when debugging, check documentation, and move around to assess what is going on.
00:09:43.840
There is a useful command in Pry called 'play,' which allows you to run a line of code without stepping through it one line at a time. For those of you familiar with the debugger, you know you can use 'next,' but with 'play,' you can quickly copy, paste, and execute a line without having to step through it.
00:10:29.240
Pry also boasts a wide array of plugins. One notable plugin is 'pry-remote,' allowing you to connect to a running server's REPL over TCP, providing a seamless debugging experience without needing to start the REPL manually every time. Another recent addition is 'pry-byebug,' which lets you navigate through your program's stack using up and down commands, enhancing your debugging workflow.
00:11:21.960
Pry also introduces 'pry-rescue,' which automatically opens the Pry console when an exception occurs, so you don't need to manually insert binding.pry in your code to stop and investigate. This automatic approach can significantly alleviate time when debugging.
00:12:02.080
Now, I would like to demonstrate this in action. I have written a simple Ruby program that simulates the Tower of Hanoi problem. It consists of just a couple of files. I will run the demo now, which initializes the Tower of Hanoi and attempts to solve it. Let's proceed with running the Ruby demo.
00:13:03.600
I realize I have not finalized the changes from earlier, so there might be an issue. Upon executing the code, we encounter an exception. To find the problem, I'll look at line 15, where the error originates. I will put a binding.pry here and rerun the code. Now that we have paused the program where I placed the binding.pry, we can examine the context of the program at that point. The comments provided by Pry will explain exactly where I am in my code.
00:14:54.240
From this point, I can see that we are indeed inside the Hanoi object, and I also have access to all methods and private methods associated with it. The debug process is straightforward, as I will check the stack to identify what has caused the problem. If the stack is not empty, I will continue iterating. Let's check the invocation again.
00:15:56.560
We will keep moving forward until we find an issue, and we can see that at this point the stack is empty. Now, I need to check the status of my Tower of Hanoi to understand what is going wrong. To assist with this, I have added a display method that allows me to visualize the current state. I'm noticing that the sizes of the disks indicate something may be off.
00:16:42.440
Upon further inspection, I realize that I am missing the smaller disks. As I re-evaluate my code, I recall inserting a double pop by mistake. I will change this back to a single pop, allowing me to execute the code once more.
00:17:55.480
After making my adjustments and rerunning the code, I encounter another exception, but this time the issue lies in a different line. The code indicates that I cannot place a disk from stack three to stack two. I will check the current state of my Tower of Hanoi again as before.
00:18:29.440
Upon analysis, it would appear I have made an error in my conditions. I will change this condition and rerun my code.
00:19:10.080
This time, all is well; I have arrived at the correct solution. I also prepared a mini test file for this project.
00:20:03.559
I run my tests now and encounter one failure.
00:20:36.760
Now it's a bit tedious to open the file and add another binding.pry for debugging. Let's explore how we can use 'pry-rescue' to simplify our process.
00:21:20.120
I will open my project repository and include 'pry-rescue' in my test file for integration with different testing frameworks. Now, when another error arises, I will see the Pry console automatically open.
00:22:32.440
This means I can investigate the state without painstakingly adding lines of binding.pry every time there's an issue.
00:23:12.640
I want to ensure I know where I am in my code to trace back the problem correctly. The ability to print the current context dramatically reduces the time needed to debug.
00:24:09.680
Next, we will check our Hanoi instance as it is currently initialized. The assertion test will evaluate whether it solves correctly and match the expected values.
00:25:46.120
Instead of typing everything out, I will utilize Pry to insert the last lines of code I need, allowing me to assert my conditions effectively.
00:26:45.480
This method streamlines my testing process. It saves me time and minimizes the need for unnecessary repetitive tasks.
00:27:51.760
I also want to show you how to extend Pry to meet your needs. For example, I will define a block command in Pry to streamline some of our work.
00:29:55.640
When I return to my project, I can implement this to create commands for more complex functions. Using Pry allows for these custom adaptations that can improve workflow.
00:31:29.200
Overall, I suggest you not hesitate to read or even change the code of the libraries you use. Don't be afraid to access and inspect your gems.
00:32:55.639
In summary, if you find code that's outside your control, remember you can edit it and quickly understand the changing dynamics. This immediate access to the console via Pry has transformed my debugging process.
00:34:12.440
Tools such as the help command can illuminate many options available to you in Pry, making it efficient for debugging within Ruby.
00:34:47.560
Thank you for your attention today. I hope this discussion of Pry has illustrated its value in debugging Ruby applications efficiently, and I encourage everyone to try it out and see the difference it can make.