Beginner

Operators in Ruby

Learn arithmetic, comparison, logical, assignment, and string operators in Ruby with practical Docker-ready examples

Operators are the verbs of a programming language—they let you add numbers, compare values, combine strings, and make decisions. Ruby gives you the familiar set of arithmetic and comparison operators you’d expect, plus a few elegant extras like the spaceship operator (<=>) and conditional assignment (||=).

What makes Ruby fascinating is a detail that flows directly from its object-oriented core: operators are actually methods. When you write 2 + 3, Ruby is really calling the + method on the integer 2 with 3 as the argument. This consistency—where even + is just a message sent to an object—is part of what gives Ruby its expressive, malleable character. It also means you can define operators on your own classes.

In this tutorial you’ll work through Ruby’s operator categories with runnable examples, then see how the “operators are methods” idea plays out, including the handy safe navigation operator (&.) for working with nil.

Arithmetic, Comparison, Logical, and Assignment Operators

This first example tours the everyday operators. Note that integer division (a / b) truncates toward zero, while introducing a float makes the whole expression floating point.

Create a file named operators.rb:

 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# Operators in Ruby
# A tour of arithmetic, comparison, logical, assignment, and string operators

a = 17
b = 5

# --- Arithmetic Operators ---
puts "== Arithmetic =="
puts "a + b  = #{a + b}"
puts "a - b  = #{a - b}"
puts "a * b  = #{a * b}"
puts "a / b  = #{a / b}"      # integer division truncates
puts "a % b  = #{a % b}"      # modulo (remainder)
puts "a ** b = #{a ** b}"     # exponentiation
puts "10.0 / 3 = #{10.0 / 3}" # a float makes the result a float
puts

# --- Comparison Operators ---
puts "== Comparison =="
puts "a == b   -> #{a == b}"
puts "a != b   -> #{a != b}"
puts "a > b    -> #{a > b}"
puts "a < b    -> #{a < b}"
puts "5 <=> 10 -> #{5 <=> 10}"  # spaceship: -1, 0, or 1

# --- Logical Operators ---
sunny = true
warm = false
puts
puts "== Logical =="
puts "sunny && warm -> #{sunny && warm}"
puts "sunny || warm -> #{sunny || warm}"
puts "!sunny        -> #{!sunny}"

# --- Assignment Operators ---
count = 10
count += 5   # 15
count -= 3   # 12
count *= 2   # 24
puts
puts "== Assignment =="
puts "count after +=5, -=3, *=2 -> #{count}"

# Conditional assignment: assign only if currently nil or false
name = nil
name ||= "Anonymous"
puts "name ||= \"Anonymous\" -> #{name}"

# --- String Operators ---
first = "Ruby"
second = "Rocks"
combined = first + " " + second  # concatenation with +
repeated = "ab" * 3              # repetition with *
puts
puts "== String =="
puts "concatenation -> #{combined}"
puts "repetition    -> #{repeated}"
puts "interpolation -> #{first} has #{first.length} letters"

# --- Operator Precedence ---
puts
puts "== Precedence =="
puts "2 + 3 * 4   = #{2 + 3 * 4}"    # * binds tighter than +
puts "(2 + 3) * 4 = #{(2 + 3) * 4}"  # parentheses force order

Operators Are Methods

Because Ruby is purely object-oriented, every operator is a method call you could also write explicitly. This is not just trivia—it means you can give operators meaning on your own objects by defining methods like + or <=>. This example also shows the safe navigation operator &., which returns nil instead of raising an error when the receiver is nil.

Create a file named operators_methods.rb:

 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
27
28
29
30
31
32
# Operators are just methods in Ruby

# Calling + and <=> as explicit methods
puts 4.+(6)        # same as 4 + 6  -> 10
puts 10.<=>(3)     # same as 10 <=> 3 -> 1

# Because + is a method, you can define it on your own class
class Money
  attr_reader :cents

  def initialize(cents)
    @cents = cents
  end

  def +(other)
    Money.new(@cents + other.cents)
  end

  def to_s
    format("$%.2f", @cents / 100.0)
  end
end

wallet = Money.new(500) + Money.new(250)
puts wallet        # uses our custom + -> $7.50

# Safe navigation operator &. returns nil instead of raising on nil
missing = nil
puts missing&.upcase.inspect   # nil (no NoMethodError)

present = "matz"
puts present&.upcase           # MATZ

Running with Docker

1
2
3
4
5
6
7
8
# Pull the official Ruby Alpine image
docker pull ruby:3.4-alpine

# Run the operators tour
docker run --rm -v $(pwd):/app -w /app ruby:3.4-alpine ruby operators.rb

# Run the "operators are methods" example
docker run --rm -v $(pwd):/app -w /app ruby:3.4-alpine ruby operators_methods.rb

Expected Output

Running operators.rb:

== Arithmetic ==
a + b  = 22
a - b  = 12
a * b  = 85
a / b  = 3
a % b  = 2
a ** b = 1419857
10.0 / 3 = 3.3333333333333335

== Comparison ==
a == b   -> false
a != b   -> true
a > b    -> true
a < b    -> false
5 <=> 10 -> -1

== Logical ==
sunny && warm -> false
sunny || warm -> true
!sunny        -> false

== Assignment ==
count after +=5, -=3, *=2 -> 24
name ||= "Anonymous" -> Anonymous

== String ==
concatenation -> Ruby Rocks
repetition    -> ababab
interpolation -> Ruby has 4 letters

== Precedence ==
2 + 3 * 4   = 14
(2 + 3) * 4 = 20

Running operators_methods.rb:

10
1
$7.50
nil
MATZ

Key Concepts

  • Operators are methods2 + 3 is really 2.+(3). This is why you can define +, -, *, <=>, and others on your own classes to make them behave naturally.
  • Integer vs. float division17 / 5 is 3 (truncated), but introducing a float like 10.0 / 3 produces a floating-point result. Mixing types promotes the result to a float.
  • The spaceship operator <=> — returns -1, 0, or 1 to indicate ordering. It powers sorting and comparison logic throughout Ruby’s standard library.
  • Short-circuit logical operators&& and || stop evaluating as soon as the result is known, returning the actual operand rather than a strict boolean.
  • Conditional assignment ||= — assigns a value only if the variable is currently nil or false. It’s a common Ruby idiom for setting defaults.
  • Strings respond to + and *+ concatenates and * repeats, but string interpolation (#{...}) is usually the most readable way to build strings.
  • Safe navigation &. — calls a method only if the receiver isn’t nil, returning nil instead of raising NoMethodError. It’s invaluable when chaining method calls on values that might be missing.
  • Precedence follows math conventions*, /, and % bind tighter than + and -; use parentheses to make intent explicit when in doubt.

Running Today

All examples can be run using Docker:

docker pull ruby:3.4-alpine
Last updated:

Comments

Loading comments...

Leave a Comment

2000 characters remaining