Ruby Get Started (Hello World)

Published by Programming Line in Ruby. Last updated .

Every programming language has a rite of passage: printing the words "Hello, World!" to the screen. It looks trivial, but that one line touches almost everything you need to get productive in Ruby — how to write a script, how to run it, and how Ruby’s built-in tools for showing output actually behave. This lesson walks through installing nothing more than Ruby itself, writing your first program, running it two different ways, and the handful of beginner mistakes that trip almost everyone up in their first week.

Overview: How Ruby Programs Run

Ruby is an interpreted, object-oriented language. When you run a Ruby file, the ruby interpreter reads your source code from top to bottom, parses it into an internal representation, and executes it immediately — there is no separate compile step you need to run yourself. A Ruby program is just a plain text file, conventionally saved with a .rb extension, containing a sequence of expressions.

A defining trait of Ruby is that everything is an object, including things that are primitives in many other languages. The number 1 is an instance of Integer, the string "Hello" is an instance of String, and even nil — Ruby’s representation of "nothing" — is the sole instance of NilClass. You can prove this to yourself at any time by calling .class on anything, even nil.class or 1.class. This matters from lesson one because it explains why methods like puts work on virtually any value: they call to_s on the object you give them and print the resulting string.

To get output on the screen, Ruby gives you three closely related but distinctly different methods, all defined on Kernel so they’re available everywhere without any setup:

Method Adds a newline? What it prints Typical use
puts Yes (unless the string already ends with one) The human-readable string form (to_s) of each argument Everyday program output
print No The human-readable string form (to_s) of each argument Output you want to control the line breaks for yourself
p Yes The programmer-readable, inspectable form (inspect) of each argument Debugging — shows quotes around strings, distinguishes nil from an empty string, etc.

You can run Ruby code in two ways: save it to a file and run ruby yourfile.rb from the terminal, or launch irb (Interactive Ruby), a REPL (read-eval-print loop) that lets you type expressions one at a time and immediately see their return value. This distinction matters more than it sounds — it is itself a very common source of beginner confusion, covered below in Common Mistakes.

Syntax

There is no special "program entry point" syntax in Ruby, unlike languages that require a main function. A Ruby file is simply executed top to bottom:

puts "Hello, World!"
  • puts is a method call. Ruby lets you omit parentheses around arguments, so puts "Hello, World!" and puts("Hello, World!") are identical.
  • "Hello, World!" is a String literal, written with double quotes so it supports interpolation (explained in the Examples section).
  • No semicolons are needed at the end of a line; a newline ends the statement. Semicolons are legal but idiomatic Ruby avoids them.
  • To run this from a terminal, save it as hello.rb and run ruby hello.rb.
$ ruby --version
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux]
$ ruby hello.rb
Hello, World!

Examples

Example 1: The classic Hello World

puts "Hello, World!"
Hello, World!

Ruby executes the single line, calls the puts method with the string as its argument, and puts writes the string to standard output followed by a newline character. That’s the entire program — no imports, no class definitions, no boilerplate required.

Example 2: puts vs. print vs. p

puts "Hello"
print "Hello"
p "Hello"
puts nil
p nil
puts [1, 2, 3]
p [1, 2, 3]
Hello
Hello"Hello"

nil
1
2
3
[1, 2, 3]

Trace it line by line: puts "Hello" prints Hello and a newline. print "Hello" prints Hello with no trailing newline, so the very next output lands on the same line. p "Hello" prints the string’s inspect form, quotes included, which is why you see "Hello" stuck right after the print output with no space between them. Then puts nil prints only a newline — an empty line — because nil.to_s is an empty string, while p nil prints the literal word nil, because inspect shows you what the object actually is, not its blank textual form. Finally, puts on an array prints one element per line, while p on an array prints the whole array in its literal, inspectable syntax on one line. This is exactly why experienced Rubyists reach for p when debugging: it never hides the difference between nil, false, an empty string, and an empty array the way puts does.

Example 3: A friendlier Hello World with keyword arguments

def greet(name:, time_of_day: "day") = "Good #{time_of_day}, #{name}! Welcome to Ruby."

puts greet(name: "Ava")
puts greet(name: "Sam", time_of_day: "morning")
Good day, Ava! Welcome to Ruby.
Good morning, Sam! Welcome to Ruby.

This introduces several modern, idiomatic pieces at once. def greet(name:, time_of_day: "day") = ... is an endless method (stable since Ruby 3.0): a one-line method definition without a matching end, whose body is a single expression that becomes the method’s return value — every Ruby method returns the value of the last expression it evaluates, whether or not you write return. name: and time_of_day: are keyword arguments; time_of_day: has a default of "day", so callers can omit it. Inside the string, #{time_of_day} and #{name} are string interpolation — Ruby evaluates the expression inside #{} and splices its to_s result directly into the surrounding double-quoted string.

How It Works Step by Step

When you run ruby hello.rb from a terminal, several things happen in order:

  • The ruby interpreter reads the entire file and parses it into an abstract syntax tree, checking that the syntax is valid (matching do/end pairs, balanced quotes and brackets, and so on). This is the exact check this site’s code examples are automatically run through.
  • Ruby then evaluates the file from top to bottom. A def statement does not run the method’s body; it only defines the method (attaching it to the current class, or to Object if it’s top-level) so it can be called later.
  • When execution reaches a method call like greet(name: "Ava"), Ruby looks up the method by name along the object’s method resolution order (its singleton class, its class, any included modules, then superclasses) and jumps into that method’s body with the arguments bound.
  • The method body runs, its final expression’s value becomes the return value, and control returns to the calling line — here, straight into puts, which converts that value to a string and writes it to standard output.
  • Once the last line of the file has executed, the interpreter exits. There’s no explicit "stop" statement needed.

Running irb instead works differently: it reads and evaluates one expression at a time, and after each one it automatically prints the return value with an => prefix — a convenience the plain ruby command does not give you.

irb(main):001:0> "Hello, World!"
=> "Hello, World!"
irb(main):002:0> puts "Hello, World!"
Hello, World!
=> nil

Notice the second line: puts returns nil (it always does), and irb dutifully echoes that nil after printing the actual text — a small detail, but a useful one for understanding what a method "gives back" versus what it prints.

Common Mistakes

Mistake 1: Expecting a saved script to auto-print, like irb does

Because irb prints the value of every line automatically, beginners often assume a saved .rb file behaves the same way.

"Hello, World!"

Run this with ruby hello.rb and it prints nothing at all. The string is evaluated and then discarded — nothing tells Ruby to display it. Only irb’s REPL loop echoes return values for you; a script has to call puts, print, or p explicitly.

puts "Hello, World!"

Mistake 2: Using single quotes and expecting interpolation

name = "Ruby"
puts 'Hello, #{name}!'
Hello, #{name}!

This runs without error, which makes it sneaky — it just prints the wrong thing. Single-quoted strings in Ruby are literal: #{...} has no special meaning inside them, so it’s printed as plain text. Interpolation only happens inside double-quoted strings.

name = "Ruby"
puts "Hello, #{name}!"
Hello, Ruby!

Mistake 3: Forgetting a matching end

def greet(name)
  puts "Hello, #{name}!"

greet("Ruby")

Every def, if, class, module, and multi-line do block needs a matching end. Leaving one off produces a SyntaxError such as unexpected end-of-input, expecting 'end', and the script won’t run at all — the parser has no way to know where the method body was supposed to stop.

def greet(name)
  puts "Hello, #{name}!"
end

greet("Ruby")
Hello, Ruby!

Best Practices

  • Use puts for ordinary program output meant for a human to read; reach for p (or its cousin pp for larger structures) whenever you’re debugging and need to see an object’s true, unambiguous form.
  • Prefer double-quoted strings by default so interpolation is available; some style guides prefer single quotes for strings with no interpolation and no escape sequences — pick one convention and stay consistent within a project.
  • Name script files in snake_case.rb (e.g. hello_world.rb), matching Ruby’s own naming conventions for methods and variables.
  • Use irb (or a project’s bin/console, common in gems) to experiment with a single expression before committing it to a file — it’s faster feedback than editing and re-running a script.
  • Remember that a method’s return value is always its last evaluated expression; don’t rely on puts inside a method to communicate a result back to a caller — puts always returns nil.
  • Check your Ruby version with ruby --version before relying on newer syntax like endless methods (def foo = ..., Ruby 3.0+) or pattern matching (case/in, stabilized in Ruby 3.0+).

Practice Exercises

  • Write a script that prints your name and favorite programming language on two separate lines using two calls to puts.
  • Write a method shout(message) that returns the message in uppercase with three exclamation marks appended (hint: look up String#upcase), then call it with puts shout("hello") and predict the output before running it.
  • Predict, then verify, what p prints for each of these on its own line: p "", p nil, p false, p 0. (Hint: in Ruby, only nil and false are falsy — 0 and "" are both truthy, even though they print differently.)

Summary

  • A Ruby program is a plain text file, usually saved as name.rb, executed top to bottom by the ruby interpreter with no separate compile step.
  • puts prints a human-readable form with a trailing newline, print does the same with no trailing newline, and p prints the programmer-readable inspect form — invaluable for debugging nil, empty strings, and empty collections.
  • irb is an interactive REPL that echoes every expression’s return value automatically; a saved script does not do this, so scripts must call puts/print/p explicitly.
  • Only double-quoted strings support #{...} interpolation; single-quoted strings are literal.
  • Every def, if, class, and multi-line block needs a matching end, unless you use a single-line endless method definition.
  • Everything in Ruby, including numbers, strings, and nil, is an object — a theme you’ll see reinforced throughout this course.