Basics

Ruby is a scripting language. So it is not compiled and then executed, but read by an interpreter and then processed line by line.

Hello World

A simple hello-world.rb program consists of one line of code:

hello-world.rb
puts 'Hello World!'

Use your favorite editor to open a new file with the filename hello-world.rb and insert the above line into it. You can then execute this Ruby program in the command line as follows:

$ ruby hello-world.rb
Hello World!
$
A program line in a Ruby program does not have to end with a semicolon. The Ruby interpreter is even so intelligent that it recognizes if a program line was split over two or more lines for the sake of readability. Indenting code is also not necessary. But it does make it much easier to read for human beings!

puts and print

If you go looking for examples on Ruby on the Internet, you will find two typical ways of printing text on the screen:

  • puts prints a string, followed by a newline.

  • print prints a string (without newline).

Example program (an extension of the program hello-world.rb):

hello-world.rb
puts 'Hello World!'
puts
puts 'zzz'
print 'Hello World!'
print
puts 'zzz'

On the screen, you will see this:

$ ruby hello-world.rb
Hello World!

zzz
Hello World!zzz
Agentic Coding Tip: Use p (or pp) for Debugging, Not puts

When an AI agent debugs a piece of Ruby code, it reaches for puts because that’s what the first tutorial introduces. For a plain string that is fine. For anything else it costs you information.

Ruby ships three closely related methods:

  • puts x prints x.to_s — the human-friendly form.

  • p x prints x.inspect and returns x — the Ruby-literal form.

  • pp x is p with pretty formatting for large structures (arrays, hashes, nested objects).

The difference matters when the value is a collection or a nil:

$ irb
>> name = nil
>> puts name
# prints an empty line, so you can't tell if it was nil or ""
>> p name
nil
>> value = { id: 42, name: "Ada" }
>> puts value
{:id=>42, :name=>"Ada"}
>> p value
{:id=>42, :name=>"Ada"}
>> pp [{ id: 1, name: "A" }, { id: 2, name: "B" }]
[{:id=>1, :name=>"A"}, {:id=>2, :name=>"B"}]

When you ask Claude to add a debug trace, puts @user will confidently print #<User:0x00007f…​> and nothing useful. p @user or pp @user prints the attributes in a form you can actually read.

Rule to add to your project’s CLAUDE.md:

For temporary debugging output in Ruby code, use `p` or `pp`
rather than `puts`. `puts` is for user-visible program
output; `p` / `pp` are for showing the Ruby value itself.
Remove all debug `p` / `pp` calls before committing.

Comments

A comment in a Ruby program starts with a #-sign and ends with a newline. As an example, I can add a comment to the hello-world.rb above:

hello-world.rb
# Program for displaying "Hello World!"
# by Stefan Wintermeyer

puts 'Hello World!'

A comment can also follow a program line:

hello-world.rb
puts 'Hello World!'  # Example comment

A #-sign within strings in inverted commas is not treated as the start of a comment. Example program:

hello-world.rb
# Example program
# by Stefan Wintermeyer

puts 'Hello World!'
puts '############'
puts
puts '1#2#3#4#5#6#'  # Comment on this

Help via ri

When programming, you do not always have a Ruby handbook available. Fortunately, the Ruby developers thought of this and provided a built-in help feature in form of the program ri.

Of course only if you have installed the documentation, which is the default. Some minimal installations (e.g. slim Docker images) strip ri pages; in that case gem install rdoc and rdoc --all on a gem’s source will regenerate them.

This is a typical chicken and egg situation. How can I explain the Ruby help feature, if we are only just getting started with Ruby? So I am going to jump ahead a little and show you how you can search for information on the class String:

$ ri String
  [...]
$
Many times it is easier and more informative to use Google instead of ri.

irb

irb stands for Interactive Ruby and is a kind of sandbox where you can play around with Ruby at your leisure. irb is launched by entering irb on the shell and ends if you enter exit.

An example is worth a thousand words:

$ irb
irb(main):001> puts 'Hello World!'
Hello World!
=> nil
irb(main):002> exit
$
I the future examples I use IRB.conf[:PROMPT_MODE] = :SIMPLE in my .irbrc config file to generate shorter irb output (without the irb(main):001> part). You can do the same by using irb --simple-prompt.