5

Given the following code:

require 'pry-byebug'

10.times.with_index do |i|
  binding.pry
  puts i
end

I'd like to "loop until i == 5 then break" while inside pry-byebug. From running it help break it seems like you can identify breakpoints by "breakpoint #" or "line #". It also seems like you can use conditions, however I'm not getting it to work:

Trying to set breakpoint on line #:

$  ruby foo.rb

From: /Users/max/Dropbox/work/tmp/pry_debug/foo.rb @ line 5 :

    1: require 'pry-byebug'
    2:
    3: 10.times.with_index do |i|
    4:   binding.pry
 => 5:   puts i
    6: end

[1] pry(main)> break foo.rb:5 if i == 5

  Breakpoint 1: /Users/max/Dropbox/work/tmp/pry_debug/foo.rb @ 5 (Enabled) Condition: i == 5


    2:
    3: 10.times.with_index do |i|
    4:   binding.pry
 => 5:   puts i
    6: end


[2] pry(main)> continue
0

From: /Users/max/Dropbox/work/tmp/pry_debug/foo.rb @ line 5 :

    1: require 'pry-byebug'
    2:
    3: 10.times.with_index do |i|
    4:   binding.pry
 => 5:   puts i
    6: end

[2] pry(main)> i
=> 1

First setting breakpoint then putting condition on break point:

➜  ~/D/w/t/pry_debug  ruby foo.rb

From: /Users/max/Dropbox/work/tmp/pry_debug/foo.rb @ line 5 :

    1: require 'pry-byebug'
    2:
    3: 10.times.with_index do |i|
    4:   binding.pry
 => 5:   puts i
    6: end

[1] pry(main)> break foo.rb:15

  Breakpoint 1: /Users/max/Dropbox/work/tmp/pry_debug/foo.rb @ 15 (Enabled)



[2] pry(main)> break --condition 1 i == 5
[3] pry(main)> c
0

From: /Users/max/Dropbox/work/tmp/pry_debug/foo.rb @ line 5 :

    1: require 'pry-byebug'
    2:
    3: 10.times.with_index do |i|
    4:   binding.pry
 => 5:   puts i
    6: end

[3] pry(main)> i
=> 1

As you can see, in both cases pry-byebug doesn't respect the condition because it stops too soon. How do I get it to work?

mbigras
  • 7,664
  • 11
  • 50
  • 111

2 Answers2

11

I think an easy way is to do it in your code:

require 'pry-byebug'

10.times.with_index do |i|
  binding.pry if i == 5
  puts i
end

Or alternatively if you want to stop at an exception, you can do something like:

require 'pry-byebug'

10.times.with_index do |i|
  puts i rescue binding.pry # if the puts command throws an exception, you'll be taken to pry
end
Coolness
  • 1,932
  • 13
  • 25
1

Remove binding.pry from the inside of the loop and put it just before 10.times:

binding.pry
10.times.with_index do |i|

Then run the code. When it hits the breakpoint then set a new breakpoint with the conditional you want and continue.

Back to your actual code. Don't do this:

10.times.with_index do |i|

Instead, this will do almost the same thing but it's simpler:

10.times do |i|

Here's what Ruby is doing:

>> 2.times.with_index.to_a
[
  [0] [
    [0] 0,
    [1] 0
  ],
  [1] [
    [0] 1,
    [1] 1
  ]
]

vs.

>> 2.times.to_a
[
  [0] 0,
  [1] 1
]

The first is passing in arrays of [0,0], [1,1], etc., so for correctness your block parameters need to be something like:

10.times.with_index do |i, j|

The second only passes the current "times" value, resulting in the more simple code.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
  • Does it not work when the `binding.pry` is inside the loop because a "breakpoint" is different than a `binding.pry`? So even though in my example I set a breakpoint, I'm still hitting my `binding.pry` on each loop through? – mbigras Jan 05 '17 at 17:22
  • Yep, you're hitting `binding.pry` each time through. Ruby doesn't have any idea that `binding.pry` is a special command it should only do once, it's just a call to a method as far as it's concerned. A breakpoint in the debugger occurs at a lower level. You should play with byebug for a while, outside of Pry, and it'll make more sense. I almost always use byebug for my debugging once I drop in, but I started in assembly language years ago so debuggers are pretty natural to me. – the Tin Man Jan 05 '17 at 17:25
  • Would you say `byebug` is like `gdb`? – mbigras Jan 05 '17 at 20:19