Beginner

Variables and Types in Ruby

Learn about variables, data types, symbols, and type conversions in Ruby with practical Docker-ready examples

Ruby is a dynamically and strongly typed language — you never declare a variable’s type, but Ruby always knows what type a value is and won’t silently coerce incompatible ones. This gives you the flexibility of a scripting language with the safety of a strong type system.

As a multi-paradigm language, Ruby treats everything as an object. That means integers, strings, booleans, and even nil all have methods you can call on them. There’s no distinction between primitive types and objects — everything participates in the same object model.

In this tutorial you’ll learn how Ruby’s type system works in practice: how to assign variables, what types are available, how to check types at runtime, and how to convert between them.

Variable Assignment

Ruby uses simple assignment with no type annotations. Variable names follow lowercase conventions with underscores for multiple words.

Create a file named variables.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
# Local variables — lowercase, no declaration needed
age = 30
name = "Alice"
pi = 3.14159
is_happy = true
nothing = nil

puts "Name: #{name}"
puts "Age: #{age}"
puts "Pi: #{pi}"
puts "Happy: #{is_happy}"
puts "Nothing: #{nothing.inspect}"

# Constants — uppercase (Ruby warns if you reassign them)
MAX_SIZE = 100
LANGUAGE = "Ruby"
puts "Max: #{MAX_SIZE}, Language: #{LANGUAGE}"

# Symbols — lightweight, immutable identifiers
status = :active
role = :admin
puts "Status: #{status}, Role: #{role}"

# Ruby's type system: everything is an object
puts age.class        # Integer
puts name.class       # String
puts pi.class         # Float
puts is_happy.class   # TrueClass
puts nothing.class    # NilClass
puts status.class     # Symbol

String interpolation with #{} is idiomatic Ruby — it calls .to_s on whatever is inside the braces and embeds the result directly in the string.

Running with Docker

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

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

Expected Output

Name: Alice
Age: 30
Pi: 3.14159
Happy: true
Nothing: nil
Max: 100, Language: Ruby
Status: active, Role: admin
Integer
String
Float
TrueClass
NilClass
Symbol

Core Types

Ruby’s built-in types cover everything you need for everyday programming:

TypeExampleNotes
Integer42, -7, 1_000_000Arbitrary precision; underscores allowed for readability
Float3.14, -0.564-bit IEEE 754 double
String"hello", 'world'Mutable; double-quoted strings support interpolation
TrueClass / FalseClasstrue, falseEach is a singleton object
NilClassnilThe absence of a value; also a singleton
Symbol:active, :nameImmutable identifier; same symbol is always the same object
Array[1, "two", :three]Ordered, mixed-type, dynamic length
Hash{ name: "Alice", age: 30 }Key-value pairs; symbol keys are most common

Type Conversions

Ruby uses explicit conversion methods rather than automatic coercions. Each type provides a family of to_* methods.

Create a file named type_conversion.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
# Integer conversions
n = 42
puts n.to_f      # Float:  42.0
puts n.to_s      # String: "42"
puts n.to_r      # Rational: 42/1

# Float to Integer truncates (does not round)
f = 3.99
puts f.to_i      # 3
puts f.ceil      # 4 (rounds up)
puts f.round     # 4 (rounds to nearest)

# String to number
puts "100".to_i       # 100
puts "3.14".to_f      # 3.14
puts "42abc".to_i     # 42  (stops at first non-numeric character)
puts "abc".to_i       # 0   (no leading digits → 0)

# Runtime type checks
value = "hello"
puts value.is_a?(String)            # true
puts value.is_a?(Integer)           # false
puts value.respond_to?(:upcase)     # true  (duck typing check)
puts value.respond_to?(:push)       # false (strings don't have push)

# Kernel#Integer and Kernel#Float raise errors on bad input
# (unlike to_i/to_f which silently return 0/0.0)
begin
  Integer("abc")
rescue ArgumentError => e
  puts "Error: #{e.message}"
end

Running with Docker

1
2
3
docker pull ruby:3.4-alpine

docker run --rm -v $(pwd):/app -w /app ruby:3.4-alpine ruby type_conversion.rb

Expected Output

42.0
42
42/1
3
4
4
100
3.14
42
0
true
false
true
false
Error: invalid value for Integer(): "abc"

Variable Scope Prefixes

Ruby uses naming prefixes to signal variable scope — no keywords like var or let are needed:

PrefixExampleScope
(none)count = 0Local to current method or block
@@name = "Alice"Instance variable (per object)
@@@@total = 0Class variable (shared across all instances)
$$debug = falseGlobal variable (avoid in most code)
UPPERCASEPI = 3.14159Constant (warns on reassignment)

For now, focus on local variables and constants — instance and class variables become relevant when you start writing classes.

Key Concepts

  • No type declarations — Ruby infers types from values; assignment is just x = value
  • Everything is an object — even 42 and nil have methods (.class, .to_s, .inspect)
  • Symbols are not strings:name and "name" are different types; symbols are immutable and memory-efficient for identifiers
  • nil is an object — not a null pointer; it’s an instance of NilClass with its own methods
  • true and false are singletonsTrueClass and FalseClass each have exactly one instance
  • Explicit conversions — use .to_i, .to_f, .to_s; prefer Integer() / Float() when you want an error on bad input
  • is_a? checks type, respond_to? checks capability — the latter is the idiomatic Ruby (duck typing) approach
  • String interpolation"Hello, #{name}!" is the idiomatic way to build strings; single-quoted strings do not interpolate

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