Ternary Operator ?: (Ruby)
The basic syntax of Ruby's ternary operator condition ? true_value : false_value. Covers usage alongside postfix if, readability issues with nested ternaries, and combining with &. (safe navigation operator).
Syntax
# Basic ternary operator syntax. # Returns true_value if the condition is truthy, false_value otherwise. result = condition ? true_value : false_value # Postfix if syntax. # Executes the expression on one line when the condition is met. expression if condition # Combined with safe navigation operator (&.). # Returns nil when object is nil; otherwise calls the method. result = object&.method ? true_value : false_value
Syntax / Operator Reference
| Syntax / Operator | Description |
|---|---|
| condition ? a : b | Returns a if the condition is truthy, b otherwise. Condenses if/else into a single expression. |
| Postfix if (expr if condition) | Executes the expression only when the condition is truthy. Suited for simple operations without assignment. |
| &. (safe navigation) | Returns nil without calling the method when the object is nil. Prevents NilClass errors. |
| Nesting | Nesting ternary operators allows multiple branches in one line, but readability drops sharply beyond two levels. |
Sample Code
Basic usage of the ternary operator — returning status based on a character's HP or grade.
ternary_basic.rb
hp = 0
status = hp > 0 ? "alive" : "defeated"
puts "Yuji Itadori's status: #{status}"
grade = "special"
puts "Satoru Gojo: #{grade == "special" ? "Special Grade sorcerer." : "Regular sorcerer."}"
power = 8500
rank_label = power >= 10000 ? "Special Grade" : "Grade 1"
puts "Megumi Fushiguro's combat rating: #{rank_label}"
is_active = true
label = is_active ? "on mission" : "standby"
puts "Nobara Kugisaki: #{label}"
ruby ternary_basic.rb Yuji Itadori's status: defeated Satoru Gojo: Special Grade sorcerer. Megumi Fushiguro's combat rating: Grade 1 Nobara Kugisaki: on mission
Choosing between postfix if and the ternary operator. The ternary operator is clearer when assigning a value; postfix if is natural for simple execution without assignment.
postfix_if_vs_ternary.rb
hp = 120
display_hp = hp > 100 ? 100 : hp
puts "Nanami's HP: #{display_hp}"
is_cursed = true
puts "Under a curse!" if is_cursed
name = "Yuji Itadori"
greeting = name.empty? ? "Unknown" : name
puts "Character: #{greeting}"
power = 9000
puts "Special move available!" if power >= 8000
ruby postfix_if_vs_ternary.rb Nanami's HP: 100 Under a curse! Character: Yuji Itadori Special move available!
Readability issues with nested ternary operators and a cleaner approach for three or more branches.
ternary_nested.rb
power = 8500
rank = power >= 10000 ? "Special Grade" : power >= 7000 ? "Grade 1" : "Grade 2 or below"
puts "Megumi Fushiguro's grade: #{rank}"
characters = [
{ name: "Yuji Itadori", power: 9200 },
{ name: "Satoru Gojo", power: 99999 },
{ name: "Megumi Fushiguro", power: 8500 },
{ name: "Nobara Kugisaki", power: 7800 },
{ name: "Kento Nanami", power: 8200 },
]
characters.each do |chara|
grade = case chara[:power]
when 10000..Float::INFINITY then "Special Grade"
when 8000..9999 then "Grade 1"
when 6000..7999 then "Semi Grade 1"
else "Grade 2 or below"
end
puts "#{chara[:name]}: #{grade} (power: #{chara[:power]})"
end
ruby ternary_nested.rb Megumi Fushiguro's grade: Grade 1 Yuji Itadori: Grade 1 (power: 9200) Satoru Gojo: Special Grade (power: 99999) Megumi Fushiguro: Grade 1 (power: 8500) Nobara Kugisaki: Semi Grade 1 (power: 7800) Kento Nanami: Grade 1 (power: 8200)
Combining &. (safe navigation operator) with the ternary operator to handle nil safely while branching.
safe_navigation_ternary.rb
class Sorcerer
attr_reader :name, :grade, :technique
def initialize(name, grade, technique)
@name = name
@grade = grade
@technique = technique
end
def special_grade?
@grade == "Special Grade"
end
end
s1 = Sorcerer.new("Yuji Itadori", "Grade 1", "Black Flash")
s2 = nil
s3 = Sorcerer.new("Satoru Gojo", "Special Grade","Hollow Purple")
[s1, s2, s3].each_with_index do |sorcerer, i|
grade_display = sorcerer&.grade ? sorcerer.grade : "Not registered"
puts "#{i + 1}: #{grade_display}"
end
puts "---"
sorcerers = [
Sorcerer.new("Megumi Fushiguro", "Semi Grade 1", "Ten Shadows"),
nil,
Sorcerer.new("Nobara Kugisaki", "Grade 1", "Straw Doll"),
Sorcerer.new("Kento Nanami", "Grade 1", "Ratio"),
nil,
]
sorcerers.each do |s|
label = s&.special_grade? ? "Special Grade sorcerer." : (s ? "Regular sorcerer." : "No data")
name = s&.name || "(unknown)"
puts "#{name}: #{label}"
end
ruby safe_navigation_ternary.rb 1: Grade 1 2: Not registered 3: Special Grade --- Megumi Fushiguro: Regular sorcerer. (unknown): No data Nobara Kugisaki: Regular sorcerer. Kento Nanami: Regular sorcerer. (unknown): No data
Notes
Ruby's ternary operator condition ? true_value : false_value condenses if/else into a single expression. It is clearest when deciding "which value to use" — such as assigning to a variable or passing an argument.
Postfix if (expression if condition) is used when running an operation without returning a value. Assigning to a variable with postfix if can leave the variable undefined when the condition is false. Use the ternary operator for conditional assignments.
Nested ternary operators are acceptable up to two levels. Beyond three levels, tracing which condition maps to which value becomes difficult, so rewriting with case/when is worth considering. &. (safe navigation operator) is handy for collections that may contain nil, but when complex conditions are involved, combining it with ordinary if/nil checks can improve readability. For an overview of conditional branching, see if / unless / postfix if.
Common Mistakes
Mistake 1: Three or more levels of nesting making the code unreadable
Nesting a ternary operator three or more levels deep makes it hard to trace which condition maps to which value. The form where conditions chain to the right is especially difficult to follow at a glance.
ng_nested_ternary.rb
power = 8500
rank = power >= 10000 ? "Special Grade" : power >= 8000 ? "Grade 1" : power >= 6000 ? "Semi Grade 1" : "Grade 2 or below"
puts "Megumi Fushiguro's grade: #{rank}"
ruby ng_nested_ternary.rb Megumi Fushiguro's grade: Grade 1
Rewriting three or more branches with case/when lines up each condition vertically, making the mapping explicit.
ok_nested_ternary.rb
power = 8500
rank = case power
when 10000..Float::INFINITY then "Special Grade"
when 8000..9999 then "Grade 1"
when 6000..7999 then "Semi Grade 1"
else "Grade 2 or below"
end
puts "Megumi Fushiguro's grade: #{rank}"
ruby ok_nested_ternary.rb Megumi Fushiguro's grade: Grade 1
Mistake 2: Postfix if assignment leaving a variable undefined when condition is false
Assigning to a variable using postfix if leaves that variable uninitialized when the condition is false. Code that follows will see nil, and calling a method on it causes NoMethodError.
ng_postfix_assign.rb
is_active = false label = "on mission" if is_active puts label.upcase
ruby ng_postfix_assign.rb ng_postfix_assign.rb:3:in `<main>': undefined method `upcase' for nil (NoMethodError)
Using the ternary operator for conditional assignment makes the value for the false case explicit.
ok_postfix_assign.rb
is_active = false label = is_active ? "on mission" : "standby" puts label.upcase
ruby ok_postfix_assign.rb STANDBY
Mistake 3: Swapping the true and false values in the ternary operator
The ternary operator returns the left value when the condition is truthy and the right value when it is falsy. Combining a negative condition (! or unless-equivalent) can inadvertently flip the mapping.
ng_ternary_condition.rb
hp = 50
status = hp <= 0 ? "alive" : "defeated"
puts "Yuji Itadori: #{status}"
ruby ng_ternary_condition.rb Yuji Itadori: defeated
Confirm what value should be returned when the condition is true before writing it. Using an affirmative condition makes the true-value and false-value mapping natural.
ok_ternary_condition.rb
hp = 50
status = hp > 0 ? "alive" : "defeated"
puts "Yuji Itadori: #{status}"
ruby ok_ternary_condition.rb Yuji Itadori: alive
If you find any errors or copyright issues, please contact us.