Data Types
Data Types in Ruby
Ruby is dynamically typed - variables don't have types, but the objects they reference do. Ruby provides several built-in data types, and everything in Ruby is an object.
1. Numbers
Ruby has several numeric classes for different types of numbers:
Integer
In Ruby 2.4+, Fixnum and Bignum were unified into Integer:
# Integers
age = 25
year = 2024
negative = -100
big_number = 999_999_999_999 # Underscores for readability
# Integer methods
puts 10.class # Integer
puts 10.even? # true
puts 15.odd? # true
puts -5.abs # 5
puts 10.times { |i| print "#{i} " } # 0 1 2 3 4 5 6 7 8 9
Float
Floating-point numbers:
price = 19.99
pi = 3.14159
scientific = 1.5e-3 # 0.0015
# Float methods
puts price.round(1) # 20.0
puts pi.ceil # 4
puts pi.floor # 3
puts (10.0 / 3).round(2) # 3.33
Rational
Represents fractions precisely:
# Creating rationals
r1 = Rational(3, 4) # 3/4
r2 = 0.75.to_r # 3/4
r3 = Rational('2/3') # 2/3
# Rational arithmetic is precise
puts Rational(1, 3) + Rational(1, 3) # 2/3
puts Rational(1, 2) * 4 # 2/1
# Convert to float
puts Rational(2, 3).to_f # 0.6666666666666666
Complex
For complex numbers:
# Creating complex numbers
c1 = Complex(3, 4) # 3+4i
c2 = 3 + 4i # 3+4i (Ruby 2.1+)
# Complex operations
puts c1 + c2 # 6+8i
puts c1.abs # 5.0 (magnitude)
puts c1.real # 3
puts c1.imaginary # 4
BigDecimal
For arbitrary precision decimal arithmetic:
require 'bigdecimal'
# Creating BigDecimal
price = BigDecimal("19.99")
tax_rate = BigDecimal("0.08")
# Precise calculations
total = price * (1 + tax_rate)
puts total.to_s('F') # 21.5892
# Rounding
puts total.round(2).to_s('F') # 21.59
2. Boolean
Ruby has two boolean values: true
and false
. Ruby also has nil
, which represents "nothing" or "no value".
is_active = true
is_deleted = false
result = nil
# Truthy and Falsy
# In Ruby, only false and nil are falsy. Everything else is truthy!
puts "0 is truthy" if 0 # This prints!
puts "Empty string is truthy" if "" # This prints!
puts "Empty array is truthy" if [] # This prints!
# Boolean methods
puts true.class # TrueClass
puts false.class # FalseClass
puts nil.class # NilClass
# Checking for nil
value = nil
puts value.nil? # true
puts value.to_s # "" (empty string)
3. Strings
Strings are sequences of characters. Ruby provides extensive string manipulation methods.
# Creating strings
single = 'Hello'
double = "World"
multiline = <<~TEXT
This is a
multiline string
with proper indentation
TEXT
# String interpolation (only in double quotes)
name = "Ruby"
greeting = "Hello, #{name}!" # "Hello, Ruby!"
calculation = "2 + 2 = #{2 + 2}" # "2 + 2 = 4"
# String methods
text = "ruby programming"
puts text.length # 16
puts text.upcase # RUBY PROGRAMMING
puts text.capitalize # Ruby programming
puts text.reverse # gnimmargorp ybur
puts text.include?("ruby") # true
puts text.split # ["ruby", "programming"]
puts text[0..3] # ruby (substring)
puts text.gsub("ruby", "Ruby") # Ruby programming
# String concatenation
str1 = "Hello"
str2 = "World"
puts str1 + " " + str2 # Hello World
puts "#{str1} #{str2}" # Hello World (interpolation)
puts str1 << " " << str2 # Hello World (modifies str1)
# Escape sequences
puts "Line 1\nLine 2" # New line
puts "Tab\there" # Tab
puts "Quote: \"Hello\"" # Escaped quotes
4. Symbols
Symbols are immutable, reusable identifiers. They're perfect for hash keys and constants.
# Creating symbols
status = :active
method_name = :to_s
hash_key = :user_id
# Symbols vs Strings
puts :ruby.object_id # Same object ID every time
puts :ruby.object_id # Same!
puts "ruby".object_id # Different object ID
puts "ruby".object_id # Different!
# Symbol methods
puts :hello.to_s # "hello"
puts "hello".to_sym # :hello
puts :hello.class # Symbol
puts :hello.upcase # :HELLO
# Common usage
user = {
:name => "John", # Traditional syntax
age: 25, # Modern syntax (Ruby 1.9+)
:email => "[email protected]"
}
5. Arrays
Arrays are ordered collections that can hold any type of object.
# Creating arrays
numbers = [1, 2, 3, 4, 5]
mixed = ["hello", 42, true, 3.14, :symbol]
nested = [[1, 2], [3, 4], [5, 6]]
empty = []
words = %w[apple banana cherry] # ["apple", "banana", "cherry"]
# Accessing elements
arr = [10, 20, 30, 40, 50]
puts arr[0] # 10 (first element)
puts arr[-1] # 50 (last element)
puts arr[1..3] # [20, 30, 40] (range)
puts arr.first # 10
puts arr.last # 50
puts arr.first(2) # [10, 20]
# Array methods
arr = [3, 1, 4, 1, 5]
puts arr.length # 5
puts arr.sort # [1, 1, 3, 4, 5]
puts arr.uniq # [3, 1, 4, 5]
puts arr.reverse # [5, 1, 4, 1, 3]
puts arr.include?(4) # true
puts arr.push(9) # [3, 1, 4, 1, 5, 9]
puts arr.pop # 9 (removes and returns)
puts arr.join("-") # "3-1-4-1-5"
# Array iteration
[1, 2, 3].each { |n| puts n * 2 }
[1, 2, 3].map { |n| n * 2 } # [2, 4, 6]
[1, 2, 3, 4, 5].select { |n| n.even? } # [2, 4]
6. Hashes
Hashes are collections of key-value pairs, similar to dictionaries in other languages.
# Creating hashes
# Old syntax
old_hash = { "name" => "Ruby", "year" => 1995 }
# Modern syntax (for symbol keys)
person = { name: "Alice", age: 30, city: "NYC" }
# Mixed keys
mixed = { :symbol => "value", "string" => 123, 42 => "number key" }
# Accessing values
user = { name: "Bob", email: "[email protected]", age: 25 }
puts user[:name] # Bob
puts user["name"] # nil (symbol != string)
puts user.fetch(:age) # 25
puts user.fetch(:phone, "N/A") # N/A (default value)
# Hash methods
person = { name: "Charlie", age: 35 }
puts person.keys # [:name, :age]
puts person.values # ["Charlie", 35]
puts person.has_key?(:name) # true
puts person.empty? # false
puts person.size # 2
# Modifying hashes
person[:city] = "Boston" # Add/update
person.delete(:age) # Remove
person.merge!(job: "Developer") # Merge another hash
# Hash iteration
person.each do |key, value|
puts "#{key}: #{value}"
end
# Default values
scores = Hash.new(0) # Default value is 0
scores[:math] += 10 # Works even though :math doesn't exist yet
puts scores[:math] # 10
7. Ranges
Ranges represent intervals of values.
# Creating ranges
numbers = 1..10 # Inclusive: 1, 2, 3...10
letters = 'a'..'z' # a, b, c...z
exclusive = 1...10 # Exclusive: 1, 2, 3...9 (not 10)
# Range methods
range = 1..5
puts range.include?(3) # true
puts range.min # 1
puts range.max # 5
puts range.to_a # [1, 2, 3, 4, 5]
# Using ranges
(1..5).each { |n| puts n }
case score
when 90..100 then "A"
when 80..89 then "B"
when 70..79 then "C"
end
Type Conversion
Ruby provides methods to convert between types:
# To String
puts 42.to_s # "42"
puts [1, 2, 3].to_s # "[1, 2, 3]"
puts :symbol.to_s # "symbol"
# To Integer
puts "42".to_i # 42
puts "42.8".to_i # 42
puts "abc".to_i # 0
# To Float
puts "3.14".to_f # 3.14
puts 42.to_f # 42.0
# To Array
puts (1..5).to_a # [1, 2, 3, 4, 5]
puts "hello".chars # ["h", "e", "l", "l", "o"]
# To Symbol
puts "method_name".to_sym # :method_name
Checking Types
# Using class method
puts 42.class # Integer
puts "hello".class # String
puts [].class # Array
# Using is_a? and kind_of?
puts 42.is_a?(Integer) # true
puts 42.is_a?(Numeric) # true (Integer is a Numeric)
puts "hello".kind_of?(String) # true
# Using respond_to?
puts "hello".respond_to?(:upcase) # true
puts 42.respond_to?(:upcase) # false