Install Ruby and restart your PC if you are on Windows machine. Type ruby -v in terminal to see the version. For me it is ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [x64-mingw32] Get started Create a file file.rb with the following code puts 'hello world' , run it from the terminal with command ruby file.rb and get output hello world . So Ruby is installed and executable. Print
puts 'hi' # hi # adds new line at the end # returns nil
print 123; print 456; print 789; # 123456789 # prints without new line
p 'hi' # "hi" # shows raw version # returns passed object
puts [1,2]
#1
#2
print [1,2] # [1, 2]
p [1,2] # [1, 2]
Load
# file1.rb
puts 'hello from file 1'
# file2.rb
load 'file1.rb'
When we execute ruby file2.rb we get hello from file 1 Comments
# single line comment
=begin
multiline
comment
=end
Variables
name = "John"
num = 123
cond = true
p name, num, cond
# "John"
# 123
# true
Types
p 1.class # Integer
p 1.234.class # Float
p "string".class # String
p false.class # FalseClass
Conversion
p 4.to_s # "4"
p 4.to_f # 4.0
p "4".to_i # 4
Escape characters
# \ backslash
# \' single quote
# \" double quote
# \a bell
# \b backspace
# \f formfeed
# \n new line
# \r carriage
# \t tab
# \v vertical tab
Constant is writable
A_CONST = 123
A_CONST = 321
p A_CONST
# file.rb:2: warning: already initialized constant A_CONST
# file.rb:1: warning: previous definition of A_CONST was here
# 321
Input
print "Enter your name: "
name = gets.chomp
p "Hello #{name}"
# Enter your name: John
# "Hello John"
print "Enter number: "
num = gets.chomp.to_i
puts "5 + #{num} = #{5 + num}"
# Enter number: 1
# "5 + 1 = 6"
Strings Multiline
str1 = 'line1
line2
line3'
p str1 # "line1
line2
line3"
str2 = %/line1
line2
line3/
puts str2 # "line1
line2
line3"
str3 = <<EOM
This is a very long string
that contains interpolation
like #{600 + 66}
EOM
puts str3
Interpolation
name = "John"
p "Hello #{name}" # "Hello John"
p 'Hello #{name}' # "Hello #{name}" # interpolation not working with single quotes
Length
name = "John"
p name.size # 4
p name.length # 4
Case
name = "joHn"
p name.upcase # "JOHN"
p name.downcase # "john"
p name.capitalize # "John"
Reverse
name = "John"
p name.reverse # "nhoJ"
Include
name = "John"
p name.include? "ohn" # true
p name.include? "xxx" # false
Start with
p 'hello'.start_with? "hel" # true
Index
p 'hello'.index("e") # 1
Count
p "vowels in the 'hello' word: " + "hello".count("aeiou").to_s # "vowels in the 'hello' word: 2"
p "consonants in the 'hello' word: " + "hello".count("^aeiou").to_s # "consonants in the 'hello' word: 3"
Strip (trim)
p " hello ".lstrip # "hello "
p " hello ".rstrip # " hello"
p " hello ".strip # "hello"
chop
p "hello".chop # "hell"
p "hello".chomp("lo") # "hel"
delete
p "hello".delete("l") # "heo"
split
p "hello".split("") # ["h", "e", "l", "l", "o"]
p "hello".split("e") # ["h", "llo"]
Concatenation
p "Hello, " "how are you" # "Hello, how are you"
p "Hello, " + "how are you" # "Hello, how are you"
p "Hello, ".concat("how are you") # "Hello, how are you"
Freeze
str = "Hi"
p str # "Hi"
str = str << " again"
p str # "Hi again"
str.freeze
str = str << " again"
p str # "Hi again" # can't modify frozen String: "Hi again" (FrozenError)
Compare
p "hi" === "hi" # true
p "hi".eql? "hi" # true
Access characters
str = "Hello from Tokyo"
p str # "Hello from Tokyo"
p str["from"] # "from"
p str[0] # "H"
p str[0, 4] # "Hell"
p str[0..10] # "Hello from"
p str[0, str.length] # "Hello from Tokyo"
p str[-4] # "o"
p str.length # 16
Operators Math
p 10 + 20 # 30
p 20 - 10 # 10
p 20 * 10 # 200
p 20 / 10 # 2
p 20 / 9 # 2
p 20.to_f / 9 # 2.2222222222222223
p 20.0 / 9 # 2.2222222222222223
p 20 / 9.0 # 2.2222222222222223
p 10 % 3 # 1
p 2 ** 3 # 8
Comparison
p 2 == 3 # false
p 2 != 3 # true
p 2 > 3 # false
p 2 < 3 # true
p 2 >= 3 # false
p 2 <= 3 # true
Logical
p (true && true) # true
p (true and true) # true
p (false || true) # true
p (false or true) # true
p (!false) # true
p (not false) # true
Array Create
p arr1 = [1, "two", 3, 4.4] # [1, "two", 3, 4.4]
p arr2 = Array.new # []
p arr3 = Array.new(5) # [nil, nil, nil, nil, nil]
p arr4 = Array.new(5, "empty") # ["empty", "empty", "empty", "empty", "empty"]
Size
arr1 = [1,2,3,4,5]
p arr1.size # 5
p arr1.length # 5
arr2 = Array.new(5)
p arr2.size # 5
Access
arr = [1,2,3,4,5]
p arr[0] # 1
p arr[1,4] # [2, 3, 4, 5]
p arr.at(1) # 2
p arr.at(5) # nil
p arr.values_at(0,1,3) # [1, 2, 4]
p arr.fetch(1) # 2
p arr.fetch(5) # index 5 outside of array bounds: -5...5 (IndexError)
p arr.first # 1
p arr.last # 5
p arr.take(2) # [1, 2]
arr.each do |value|
p value # 1 2 3 4 5
end
Manipulate
arr = [1,2,3,4,5]
p arr.push(6) # [1, 2, 3, 4, 5, 6]
p arr << 7 # [1, 2, 3, 4, 5, 6, 7]
p arr.unshift(0) # [0, 1, 2, 3, 4, 5, 6, 7]
p arr.insert(3, 666) # [0, 1, 2, 666, 3, 4, 5, 6, 7]
p arr.pop # 7
p arr # [0, 1, 2, 666, 3, 4, 5, 6]
p arr.shift # 0
p arr # [1, 2, 666, 3, 4, 5, 6]
p arr.delete(666) # 666
p arr # [1, 2, 3, 4, 5, 6]
p arr.drop(3) # [4, 5, 6]
p arr # [1, 2, 3, 4, 5, 6]
Include?
arr = [1, 2, 3, 1, 2, 3]
p arr.include?(2) # true
Count
arr = [1, 2, 3, 1, 2, 3]
p arr.count(2) # 2
Empty?
arr = []
p arr.empty? # true
Join
arr = [1, 2, 3]
p arr.join(" ") # "1 2 3"
p arr.join # "123"
Reverse
arr = [1, 2, 3]
p arr.reverse # [3, 2, 1]
Select
arr = [1, 2, 3, 4, 5]
p arr.select { |num| num > 2 } # [3, 4, 5]
p arr # [1, 2, 3, 4, 5]
flatten
p [1, 2, [3, 4, 5]].flatten # [1, 2, 3, 4, 5]
p [1, 2, [3, [4, 5]]].flatten # [1, 2, 3, 4, 5]
each
arr = [1, 2, 3, 4, 5]
arr.each do |el|
p el
end
# 1 2 3 4 5
map
arr = [1, 2, 3, 4, 5]
p arr.map { |el| el * 2 } # [2, 4, 6, 8, 10]
concat
arr = [1, 2, 3]
p arr.concat([4, 5, 6]) # [1, 2, 3, 4, 5, 6]
p arr # [1, 2, 3, 4, 5, 6]
uniq
arr = [1, 1, 2, 2, 3, 3]
p arr.uniq # [1, 2, 3]
p arr # [1, 1, 2, 2, 3, 3]
Hash (object) Create
hash1 = {
"name" => "John",
"sex" => "male",
"age" => 35
}
hash2 = Hash[
"name", "Jane",
"sex", "female",
"age", 35
]
p hash1.size # 3
p hash2.size # 3
Default key
hash = Hash.new("no such key")
p hash["country"] # "no such key"
Access
hash = {
"name" => "Jane",
"sex" => "female",
"age" => 35
}
p hash["name"] # "Jane"
p hash["sex"] # "female"
p hash["age"] # 35
p hash["country"] # nil
hash.each do |key, value|
p "#{key} : #{value}"
end
# "name : Jane", "sex : female", "age : 35"
Add
hash = {
"name" => "Jane",
"sex" => "female",
"age" => 35
}
hash["country"] = "USA"
p hash["country"] # "USA"
Delete
hash = {
"name" => "Jane",
"sex" => "female",
"age" => 35
}
hash.delete("name")
p hash # {"sex"=>"female", "age"=>35}
Merge
hash1 = {
"name" => "Jane",
"sex" => "female",
"age" => 35
}
hash2 = {
"age" => 66,
"country" => "USA",
}
p hash1.merge(hash2) # {"name"=>"Jane", "sex"=>"female", "age"=>66, "country"=>"USA"}
p hash1 # {"name"=>"Jane", "sex"=>"female", "age"=>35}
Update
hash1 = {
"name" => "Jane",
"sex" => "female",
"age" => 35
}
hash2 = {
"age" => 66,
"country" => "USA",
}
p hash1.update(hash2) # {"name"=>"Jane", "sex"=>"female", "age"=>66, "country"=>"USA"}
p hash1 # {"name"=>"Jane", "sex"=>"female", "age"=>66, "country"=>"USA"}
Has key, value
hash = {
"name" => "Jane",
"sex" => "female",
"age" => 35
}
p hash.has_key?("name") # true
p hash.has_value?("Jane") # true
Has key, value
hash = {}
p hash.empty? # true
Conditions if
if 2 > 1
p "2 is greater than 1"
end
# "2 is greater than 1"
p "2 is greater that 1" if 2 > 1 # "2 is greater that 1"
if-else
if 1 > 2
p "1 is greater than 2"
else
p "1 is not greater than 2"
end
# "1 is not greater than 2"
else-if
if 2 > 2
p "2 is greater than 2"
elsif 2 == 2
p "2 is equal 2"
else 2 < 2
p "2 is less than 2"
end
# "2 is equal 2"
unless (negated 'if')
x = 3
unless x < 5
p 'x >= 5'
else
p 'x < 5'
end
# "x < 5"
Ternary statement
yesOrNo = 2 > 1 ? 'yes' : 'no'
p yesOrNo # "yes"
Case statement
print "Enter day num: "
day = gets.chomp.to_i
case day
when 1
p "Mon"
exit
when 2
p "Tue"
exit
when 3
p "Wed"
exit
when 4
p "Thu"
exit
when 5
p "Fri"
exit
when 8..Float::INFINITY
p "not valid"
exit
else
p "weekend"
end
# Enter day num: 5
# "Fri"
# Enter day num: 7
# "weekend"
# Enter day num: 10
# "not valid"
Loops For
for i in 1..5
p i
end
# 1 2 3 4 5
for i in [1, 2, 3, 4, 5]
p i
end
# 1 2 3 4 5
arr = [1, 2, 3, 4, 5]
for i in arr
p i
end
# 1 2 3 4 5
while
x = 1
while x < 5 do
p x
x += 1
end
# 1 2 3 4
do
loop do
p "enter a num > 10"
num = gets.chomp.to_i
if num > 10
p "thank you"
break
end
end
# "enter a num > 10"
# 11
# "thank you"
until
i = 1
until i === 5
p i
i += 1
end
# 1 2 3 4
each
arr = [1, 2, 3, 4, 5]
arr.each do |num|
p num
end
# 1 2 3 4 5
(1..5).each do |num|
p num
end
# 1 2 3 4 5
break
for i in 1..5
if i === 3
break
end
p i
end
# 1 2
next
for i in 1..5
if i === 3
next
end
p i
end
# 1 2 4 5
redo (repeat current iteration)
i = 1
while i < 5
p i
i += 1
# redo if i === 5
end
# 1 2 3 4
i = 1
while i < 5
p i
i += 1
redo if i === 5
end
# 1 2 3 4 5
retry
for i in 1..5
begin
p i
raise if i === 5
rescue
retry
end
end
# 1 2 3 4 5 5 5 5 5 5 5 5 5...
Function Function declaration
def hello
p "hello from method"
end
hello # "hello from method"
def hello()
p "hello from method"
end
hello() # "hello from method"
def hello(name)
p "hello from #{name}"
end
hello('John') # "hello from John"
def hello(name = "John")
puts "Hello from #{name}"
end
hello # "hello from John"
Function expression (lambda)
hello = lambda {p 'hello'}
hello.call # "hello"
hello.() # "hello"
hello.[] # "hello"
hello.=== # "hello"
Arrow function
hello = -> { puts "hello" }
hello.call # "hello"
hello = -> (arg) { puts "hello " + arg }
hello.call("John") # "hello John"
Catch errors (begin-rescue)
print "Enter a number : "
first_num = gets.to_i
print "Enter Another : "
second_num = gets.to_i
begin
answer = first_num / second_num
rescue # You could use rescue ZeroDivisionError
puts "You can't divide by zero"
exit
end
puts "#{first_num} / #{second_num} = #{answer}"
# Enter a number : 5
# Enter Another : 0
# You can't divide by zero
Symbols Symbols are strings that can't be changed Use them to speed string comparisons Use them if string value won't change & no need to access to string methods Many Ruby methods take symbols as arguments Symbols are used as keys for hashes
p :derek # :derek
p :derek.to_s # "derek"
p :derek.class # Symbol
p :derek.object_id # 1101468
Class Initialize, getter, setter, method, self
class Car
@brand
@model
@topSpeed
def initialize(brand = "some brand", model = "some model", topSpeed = 100)
@brand = brand
@model = model
@topSpeed = topSpeed
puts "creating Car object"
end
# setter 1
def set_brand(new_brand)
# We can eliminate bad input in our setters
if new_brand == "Apple"
puts "Apple is not a car brand"
else
@brand = new_brand
end
end
# setter 2
def model=(new_model)
@model = new_model
end
# getter
def brand
@brand
end
def model
@model
end
def topSpeed
@topSpeed
end
# method
def tellAboutCar()
p "your car is #{self.brand} #{self.model} with top speed #{self.topSpeed}"
end
end
someCar = Car.new
p someCar.brand # "some brand"
someCar.set_brand("Toyota")
p someCar.brand # "Toyota"
someCar.set_brand("Apple") # Apple is not a car brand
p someCar.brand # "Toyota"
tesla = Car.new("Tesla", "Model 3", "220")
p tesla.brand # "Tesla"
tesla.model = "Modle Y"
tesla.tellAboutCar() # "your car is Tesla Modle Y with top speed 220"
Accessors (shortcut for getters & setters)
class Dog
attr_reader :name, :height, :weight
attr_writer :name, :height, :weight
# or just
# attr_accessor :name, :height, :weight
def bark
return "Generic Bark"
end
end
rover = Dog.new
rover.name = "Rover"
p rover.name # "Rover"
p rover.bark # "Generic Bark"
Inherit
class Dog
attr_accessor :name, :height, :weight
def bark
return "Generic Bark"
end
end
class GermanShepard < Dog
def bark
return "Loud bark"
end
end
chelsy = GermanShepard.new
chelsy.name = "Chelsy"
p chelsy.name, chelsy.bark() # "Chelsy" "Loud bark"
Module Modules hold methods, but unlike classes, modules can not be instantiated, meaning it is not possible to create objects from a module. With modules we can share methods between classes.
# animal.rb
module Animal
def make_sound
puts "Grrrrrr"
end
end
# file.rb
load 'animal.rb'
class Dog
include Animal
end
rover = Dog.new
rover.make_sound # Grrrrrr
Enumerable Classes that include the Enumerable module get nice methods. To make class enumerable we have to define each function.
class Menu
include Enumerable
# Each provides items one at a time
def each
yield "pizza"
yield "spaghetti"
yield "salad"
yield "bread"
yield "water"
end
end
menu_options = Menu.new
# cycle through all items
menu_options.each do |item|
puts "Would you like : #{item}" # "pizza" "spaghetti" "salad" "bread" "water" "pizza"
end
# check if we have an item
p menu_options.find { |item| item == "apple"} #nil
p menu_options.find { |item| item == "pizza"} # pizza
# return items over 5 letters in length
p menu_options.select { |item| item.size > 5 } # ["spaghetti"]
# reject items that meet the criteria
p menu_options.reject { |item| item.size > 5 } # ["pizza", "salad", "bread", "water"]
# first item
p menu_options.first # "pizza"
# first 2 items
p menu_options.take(2) # ["pizza", "spaghetti"]
# everything except first 2
p menu_options.drop(2) # ["salad", "bread", "water"]
# min
p menu_options.min # "bread"
# max
p menu_options.max # "water"
# sort
p menu_options.sort # ["bread", "pizza", "salad", "spaghetti", "water"]
# reverse
menu_options.reverse_each { |item| p item} # "water", "bread", "salad", "spaghetti", "pizza"
File Create, add, read
# Returns a File object for writing
myFile = File.new("file.txt", "w")
# write text in the file
myFile.puts "1st line"
myFile.puts "2nd line"
# Closes the file
myFile.close
# Read data from the defined file
data_from_file = File.read("file.txt")
p data_from_file # "1st line\n2nd line\n"
Append
myFile = File.new("file.txt", "a")
myFile.puts "3rd line"
myFile.close
p File.read("file.txt") # "1st line
2nd line
3rd line
"
Process text
File.open("file.txt") do |line|
line.each do |item|
p item
end
end
# "1st line\n"
# "2nd line\n"
# "3rd line\n"
Ruby cheat-sheet on every property and method.