binding.irb X binding.pry?Which one is better at debugging in rails?
We can start a comparison by a very simple example via rails c.
binding.irb example
def sum(a, b)
binding.irb
puts a
puts b
a + b
end
binding.pry example
def sum(a, b)
binding.pry
puts a
puts b
a + b
end
binding.irb[1] pry(main)> def sum(a, b)
[1] pry(main)* binding.irb
[1] pry(main)* puts a
[1] pry(main)* puts b
[1] pry(main)* a + b
[1] pry(main)* end
=> :sum
[2] pry(main)> sum(5, 2)
irb(main):001:0> sum(10, 3)
irb(main):001:0> # ?? am I debugging or not?
=> nil
irb(main):002> whereami
The current context doesn't have code.
=> nil
irb(main):003> whereami
The current context doesn't have code.
=> nil
irb(main):004> a
irb(main):005> b
=> 3
irb(main):006> b
=> 3
irb(main):007> a
=> 10
irb(main):008> puts a
10
=> nil
irb(main):009> puts b
3
=> nil
irb(main):010> a + b
=> 13
irb(main):011> exit
10
3
=> 13
irb(main):002> a + b
=> 7
irb(main):003> exit
5
2
=> 7
binding.pry[1] pry(main)> def sum(a, b)
[1] pry(main)* binding.pry
[1] pry(main)* puts a
[1] pry(main)* puts b
[1] pry(main)* a + b
[1] pry(main)* end
=> :sum
[2] pry(main)> sum(5, 2)
From: (pry):3 Object#sum:
1: def sum(a, b)
2: binding.pry
=> 3: puts a
4: puts b
5: a + b
6: end
[1] pry(main)> puts a
5
=> nil
[2] pry(main)> puts b
2
=> nil
[3] pry(main)> whereami
From: (pry):3 Object#sum:
1: def sum(a, b)
2: binding.pry
=> 3: puts a
4: puts b
5: a + b
6: end
[4] pry(main)> a
=> 5
[5] pry(main)> b
=> 2
[6] pry(main)> a + b
=> 7
[7] pry(main)> exit
5
2
=> 7
While binding.irb has a very interesting promise, like serving as the main debugger in rails, it comes with bugs and drawbacks that simply don't exist when we using binding.pry for the debugging process.
binding.pry looks more clear for the debugging process, particularly because binding.pry outputs to the user the code where binding.pry is located as soon as the code hits this debugger, while binding.irb doesn't output anything to the user when the code hits this debugger (even if we call whereami sometimes it doesn't output anything (😱), which is very confusing in terms of usability).
In addition, there are bugs in binding.irb related to not outputting the value of a variable when we call it! We can check it by looking at the above pictures and noticing the a variable value was not shown to the user here:
irb(main):004> a
On the other hand, binding.pry doesn't have this bug and always output the value of a variable when we call it and press enter.
As a last note... Is there a way to fix all of these bugs in binding.irb? In case not, I would recommend to keep using binding.pry for the debugging process to avoid headaches.