Question
I want to repeatedly ask the user for names, store each non-empty name in an array, and stop when the user enters an empty string.
Here is my current Ruby code:
people = []
info = 'a' # initialize with a non-empty value so the loop runs at least once
while !info.empty?
info = gets.chomp
people << Person.new(info) unless info.empty?
end
This feels like a case for a do ... while loop, because I want the body to run once before checking the condition.
I tried writing it like this:
people = []
begin
info = gets.chomp
people << Person.new(info) unless info.empty?
end while !info.empty?
Ruby does not seem to support the do ... while syntax used in some other languages. What is the Ruby way to handle this pattern more cleanly, without needing to initialize info to a random value first?
Short Answer
By the end of this page, you will understand how Ruby handles loops that must run at least once. You will learn Ruby's begin ... end while form, the common loop do pattern with break, and how to write cleaner input-reading loops without fake initial values.
Concept
In some languages, a do ... while loop runs the code block first and checks the condition afterward. This is useful when the loop body must execute at least one time.
Ruby does not use the exact do ... while syntax, but it does support the same idea through:
begin ... end whileloop do ... break- reading input first, then checking whether to continue
This matters because many real programs need to:
- ask for user input at least once
- retry until valid input is entered
- keep processing until a stop condition appears
A common beginner mistake is forcing a normal while loop to behave like a post-condition loop by giving a variable a fake initial value. That works, but it is not the clearest Ruby style.
In Ruby, the more idiomatic solution is usually one of these:
begin
# code runs first
end while condition
or:
loop do
# code runs
break if stop_condition
end
Both patterns avoid unnecessary placeholder values and express your intent more clearly.
Mental Model
Think of a normal while loop like a security guard standing before a door:
- The guard checks the condition first.
- If the condition fails, you never enter.
A post-condition loop is like a guard standing after the room:
- You always go in once.
- After that, the guard decides whether you can go around again.
Your input example fits the second model:
- ask for a name
- if it is empty, stop
- otherwise store it and repeat
So the important idea is not the exact words do ... while, but the behavior: run once, then decide whether to continue.
Syntax and Examples
1. begin ... end while
Ruby supports a post-condition loop using begin ... end while.
people = []
begin
info = gets.chomp
people << Person.new(info) unless info.empty?
end while !info.empty?
Why this works
begin ... endruns firstwhile !info.empty?is checked after the block- the loop stops when the user enters an empty string
2. loop do with break
This is often the most idiomatic Ruby approach.
people = []
loop do
info = gets.chomp
break if info.empty?
people << Person.new(info)
end
Why many Ruby developers prefer this
- very readable
- no fake initial value needed
- stopping condition is easy to see
3. Simple example without Person
names = []
loop do
name = gets.chomp
break if name.empty?
names << name
end
p names
If the user enters:
Alice
Bob
Then names becomes:
["Alice", "Bob"]
Step by Step Execution
Consider this Ruby code:
names = []
loop do
name = gets.chomp
break if name.empty?
names << name
end
Now imagine the user types:
Alice
Bob
Step-by-step
-
names = []- An empty array is created.
-
loop do- Ruby starts an infinite loop.
- It will keep running until
breakis reached.
-
First iteration:
name = gets.chomp- User enters
Alice nameis now"Alice"break if name.empty?"Alice".empty?isfalse, so continuenames << namenamesbecomes["Alice"]
-
Second iteration:
- User enters
Bob nameis now"Bob"name.empty?isfalsenames << namenamesbecomes["Alice", "Bob"]
- User enters
-
Third iteration:
- User just presses Enter
gets.chompreturns""name.empty?istruebreakstops the loop
-
Final result:
["Alice", "Bob"]
This pattern is easy to trace because the exit condition is checked immediately after reading input.
Real World Use Cases
This pattern appears often in Ruby programs.
User input collection
emails = []
loop do
email = gets.chomp
break if email.empty?
emails << email
end
Used in small CLI tools, setup scripts, or interview exercises.
Retry until valid input
age = nil
loop do
print "Enter your age: "
input = gets.chomp
if input.match?(/^\d+$/)
age = input.to_i
break
end
puts "Please enter a valid number."
end
Used in terminal apps and admin scripts.
Reading lines until a sentinel value
lines = []
loop do
line = gets.chomp
break if line == "STOP"
lines << line
end
Useful when processing text input until a special command appears.
Menu-driven programs
loop do
puts "1. Add"
puts "2. Exit"
choice = gets.chomp
break if choice == "2"
puts "You chose: #{choice}"
end
Common in beginner Ruby console applications.
Real Codebase Usage
In real Ruby projects, developers usually pick the loop form that best matches the task.
Common pattern: guard clause with break
loop do
input = gets.chomp
break if input.empty?
process(input)
end
This is clean because the stop condition is handled early.
Validation before object creation
users = []
loop do
name = gets.chomp.strip
break if name.empty?
users << User.new(name: name)
end
This avoids creating invalid objects from empty input.
Using until for opposite logic
Sometimes Ruby code expresses the condition in reverse:
begin
input = gets.chomp
puts "You typed: #{input}"
end until input == "quit"
This works, but many teams still prefer loop do plus break because it is straightforward.
Error handling inside loops
loop do
input = gets.chomp
break if input.empty?
begin
people << Person.new(input)
rescue StandardError => e
puts "Could not create person: #{e.message}"
end
end
This style is useful when each iteration may fail independently.
Why loop do is common
- clear start and stop behavior
- easy to combine with
next,break, and validation - avoids awkward setup code before the loop
Common Mistakes
1. Using a fake initial value just to start the loop
This works, but it is usually less clear:
info = "a"
while !info.empty?
info = gets.chomp
end
Better
loop do
info = gets.chomp
break if info.empty?
end
2. Creating objects before checking for empty input
Broken version:
loop do
info = gets.chomp
people << Person.new(info)
break if info.empty?
end
Problem
This creates Person.new("") when the user presses Enter.
Better
loop do
info = gets.chomp
break if info.empty?
people << Person.new(info)
end
3. Confusing not with !
Ruby allows both:
not info.empty?
!info.empty?
But ! is more common and often clearer in conditions.
4. Typo in variable names
The original example showed both Copypeople and people.
Broken version:
Copypeople = []
people << Person.new(info)
Problem
You are using two different variable names.
Better
people = []
Use one consistent local variable name.
5. Using a constant accidentally
In Ruby, names starting with a capital letter are constants.
People = []
That is not the same as a normal local variable.
Better
people = []
Use lowercase for local variables.
6. Forgetting chomp
Without chomp, pressing Enter leaves a newline in the string.
input = gets
Then input.empty? may not behave as expected because the string contains "\n".
Better
input = gets.chomp
Comparisons
| Approach | Runs at least once? | Idiomatic in Ruby? | Best use |
|---|---|---|---|
while condition | No | Yes | When you can check before entering |
begin ... end while condition | Yes | Valid, less common | When you want true post-condition behavior |
loop do ... break | Yes | Very common | Input loops, validation, repeated actions |
until condition | No | Yes | When logic reads better as “keep going until” |
begin ... end until condition | Yes | Valid | Post-condition loop with reversed logic |
Example comparison
while
info = gets.chomp
while !info.empty?
people << Person.new(info)
info = gets.chomp
end
This can work, but it forces one read before the loop.
begin ... end while
begin
info = gets.chomp
people << Person.new(info) unless info.empty?
end while !info.empty?
This matches the idea of a classic post-condition loop.
loop do
loop do
info = gets.chomp
break if info.empty?
people << Person.new(info)
end
This is often the clearest Ruby version.
not vs !
| Form | Meaning | Notes |
|---|---|---|
!value | logical negation | most common in conditions |
not value | logical negation | valid, but lower precedence can be confusing |
Cheat Sheet
Post-condition loops in Ruby
Ruby does not use do ... while
Use one of these instead:
begin
# code
end while condition
loop do
# code
break if condition
end
Best pattern for user input
items = []
loop do
input = gets.chomp
break if input.empty?
items << input
end
Useful rules
whilechecks the condition firstbegin ... end whilechecks after running onceloop doruns forever untilbreak- use
breakto stop aloop do - use
nextto skip to the next iteration - use
chompto remove the trailing newline from input
Common checks
input.empty?
input == "quit"
input.strip.empty?
Watch out for
- fake initial values like
info = "a" - creating objects before checking for blank input
- capitalized variable names, which become constants
- forgetting
chomp
Clean pattern with object creation
people = []
loop do
name = gets.chomp
break if name.empty?
people << Person.new(name)
end
FAQ
Is there a do ... while loop in Ruby?
Not with that exact syntax. Ruby uses begin ... end while for post-condition loops.
What is the Ruby equivalent of do ... while?
The closest equivalent is:
begin
# code
end while condition
Many Ruby developers also use loop do with break.
Which is more idiomatic in Ruby: begin ... end while or loop do?
Both are valid, but loop do with break is more commonly seen in Ruby code.
Why not just use while?
A while loop checks the condition before the first iteration. If you need the loop body to run at least once, while alone is awkward.
Why should I use chomp with gets?
gets includes the newline character from pressing Enter. chomp removes it so empty input becomes "".
Should I use not or ! in Ruby conditions?
! is usually preferred because it is shorter and avoids precedence confusion.
How do I stop when the user enters only spaces?
Use strip.empty? instead of empty?:
break if input.strip.empty?
Mini Project
Description
Build a small Ruby console program that collects task names from the user until they press Enter on a blank line. This demonstrates the Ruby way to write a loop that must run at least once, while also practicing array building and input validation.
Goal
Create a program that repeatedly accepts task names and stores them in an array until the user enters a blank line.
Requirements
- Start with an empty array for tasks.
- Repeatedly ask the user to enter a task.
- Stop when the user enters a blank line.
- Store only non-empty task names.
- Print the final list of tasks at the end.
Keep learning
Related questions
Add a Default Value to an Existing Column in a Rails Migration
Learn how to add or change a default value on an existing database column using Rails Active Record migrations safely.
Calling a Class Method from an Instance in Ruby
Learn how to call a class method from an instance in Ruby using self.class, with examples, pitfalls, and practical usage patterns.
Calling an Overridden Monkey-Patched Method in Ruby
Learn how to call the original method when monkey patching in Ruby, including alias_method patterns, examples, pitfalls, and practical usage.