Working with Ruby
Hi, I am Jan. This is my old Ruby blog. I still post about Ruby, but I now do it on idiosyncratic-ruby.com. You should also install Irbtools to improve your IRB.

Little heplers for Ruby print debugging

Not everyone likes debuggers. I rather print the debug values myself – it works and I do not need to learn a debugger :P

The Zucker debug package includes various print debugging helpers.

q

Like p, but outputs on a single line, values separated by spaces.

 1
2
3
4
5
6
7
8
9
### usage
# q "zucker", '', {6=>7}, 5, 2.3, :o
### will output
# "zucker"  ""  {6=>7}  5  2.3  :o

def q(*args)
  puts args.map( &:inspect )*'  ' unless args.empty?
end
alias qq q

o

Outputs the current line, the current file, the current method and a label (if given).

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
### usage
# o
# o:Label
### example outputs
# Reached method `irb_binding', line 1 of file (irb)
# Reached method `abc', line 4 of file 123.rb
# Label: reached method `de', line 9 of file example.rb

def o(desc = nil)
  caller[0].rindex( /:(\d+)(:in (`.*'))?$/ )
  m = $3 ? "method #$3, " : ""
  d = desc ? "#{desc}: r" : 'R'

  # lol, I need to change the syntax highlighter...
  # the "syntax" gem *crashed* when I wrote "#$`"
  puts "#{d}eached #{m}line #{$1} of file #{$`}"
end
alias oo o

c

Displays the method call stack.

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
### usage
# def qwe
#  c
# end
#
# def rtz
#   qwe
# end
#
# rtz
#
### example output
# <main>
#   rtz
#     qwe


def c
  puts caller.reverse.map.with_index{ |m, i|
    m.rindex( /:\d+(:in `(.*)')?$/ )
    "  "*i + $2
  }
end
alias cc c

# The version in Zucker also filters irb methods

Object#d

Outputs to stdout and returns self.

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# example usage
require 'zucker/debug'

some.d.methods.d.noone.d.knows.d
# ...outputs 4 lines with the inspected objects
# => (result)

21 + Math.sin(42).d
# outputs -0.916521547915634
# => 20.0834784520844

name = 'Earth'
'Hello ' + name.d{|e| "The length is: #{e.size}"}
# outputs "The length is: 5"
# => 'Hello Earth'

Binding#inspect

Displays your current variables.

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# irb example
>> require 'zucker/debug'
=> true
>> a=3
=> 3
>> binding
=> #<Binding:0x94c4b50>
local vars
 - a: 3
 - _: #<Binding:0x94c4b50>
(instance vars)
 - none
self
 - main
block_given?
 - false

Object#m

An ordered method list.

A little detail

You do not need to be afraid of having short variables names that might interfere with debug method names. As with p, Ruby does not care, if there is a local variable with that name, they just live side by side. Should a debug method be overwritten, you still have the double-character-variant (e.g. qq for q).

This is probably the last post on Zucker for a while. The development of Zucker went great last month. I am satisfied with the result and don’t think about pushing another version this month ;).

Creative Commons License

Anonymous | September 08, 2010

You don't want to use a debugger, but you prefer a bunch of meaningless one-letter method names that are difficult to remember and impossible to search for?

J-_-L | September 08, 2010

Hello,
there are just four of those one-letter-methods. These are my mneomics:
<code>q</code> just looks like <code>p</code> and it does almost the same.
<code>c</code> stands for <b>c</b>allstack.
<code>.d</code> just means debug.
And ok, <code>o</code> just looks better than <code>r</code> or <code>l</code> for "output reached line".

Mark Wilden | September 09, 2010

My lll gem does similar things. It prints an expression and its value, so output is self-labelling: https://rubydoc.info/gems/lll/1.1.0/frames