IT212 Data Structure

Unit 2: Ruby Programming

R Batzinger

2026-01-17

Ruby programming language

Why Ruby?

  • Ruby is a dynamic, object-oriented programming language known for its simplicity and productivity.
  • Ruby real-world applications span web development, automation, web scraping, DevOps, and graphics often through library extentions.
  • Ruby provides development tools to support design, testing, documentation and formatting of code.
  • Ruby fully supports Asian languages using both Unicode and national code spaces developed by Yukihiro Matsumoto
  • Ruby facilitates the inspection of storage requirements of data structures

Ruby development tools

  • Robocop - A Ruby static code analyzer and formatter, based on the community Ruby style guide.
  • rdoc - A Ruby static code analyzer and formatter, based on the community Ruby style guide.
  • Rake - a tool that uses standard Ruby syntax.
  • Test::Unit - checks that code is compatible with design assertions
  • Cucumber - a behavior driven development system to tests the code against the design specifications
  • Rmagick - a graphic library that interfaces with imagemagick to create and modify graphic images.
  • DBI: provides a database-agnostic API to load the appropriate DBD (Database Driver) for your database (e.g., MySQL, PostgreSQL, SQLite)

Ruby resources

  • Central Ruby site: https://www.ruby-lang.org/en/

  • Online ide: https://try.ruby-lang.org/playground/

  • Download page:

    • Windows: https://rubyinstaller.org/downloads/
    • Other Os: https://www.ruby-lang.org/en/documentation/installation/
  • Tutorial: https://try.ruby-lang.org https://pine.fm/LearnToProgram/

  • Documentation: https://ruby-doc.org/

  • Programming Manual: https://ruby-doc.org/docs/ruby-doc-bundle/ProgrammingRuby/index.html

Ruby standard data types

  • Numerical primitive objects
    • Integer (with Automatic conversion between Fixnum and Bignum)
    • Float
    • Rational
    • Complex
  • Textual primitive objects
    • Characters (with code point)
    • Symbols
  • Collective objects
    • Object Classes
    • Array - (includes stacks and queues)
    • Hash - (associated array)
    • String
    • Enumerable

Code examples


#!/usr/bin/env ruby
# Demonstration of Ruby's standard numeric data types

puts "Ruby Data Types".upcase

def unitheader(header)
  puts
  puts header
  puts "-" * 65
end

def example(lbl, op)
   x = eval(op)
   puts " #{lbl.ljust(12)}, #{op.ljust(27)} #{x} (#{x.class})"
end

unitheader("Integer examples:")
example("@int_a","@int_a = 42")
example("@int_b","@int_b = -100")
example("Sum:","@int_a + @int_b")

unitheader("Float examples:")
example("@float_a","@float_a=3.14159")
example("@float_b","@float_b = -0.5")
example("Product:","@float_a * @float_b")

unitheader("Rational examples:")
example("@rational_a","@rational_a = Rational(2,3)")
example("@rational_b","@rational_b = 5r")
example("Sum:","@rational_a + @rational_b")

unitheader("Complex examples:")
example("@complex_a","@complex_a = Complex(2,3)")
example("@complex_b","@complex_b = 4 + 5i")
example("Sum:","@complex_a + @complex_b")

unitheader("Type conversions:")
example("Int2Float:","@int_a.to_f")
example("Float2Int","@float_a.to_i")
example("Int2Rational","@int_a.to_r")
example("Int2Complex","@int_a.to_c")

unitheader("Automatic type promotion:")
example("Int2Float", "@int_a + @float_a")
example("Int2Rational","@int_a + @rational_a")
example("Rational2Flt","@rational_a+@float_a")
example("Complex2Int","@complex_a + @int_a")

unitheader("Edge case: very large integers")
example("@bigInt", "@big_int = 10**20")
example("inc(@bigInt)","@big_int += 1")
puts "-" * 65

Output

RUBY DATA TYPES

Integer examples:
-----------------------------------------------------------------
 @int_a      , @int_a = 42                 42 (Integer)
 @int_b      , @int_b = -100               -100 (Integer)
 Sum:        , @int_a + @int_b             -58 (Integer)

Float examples:
-----------------------------------------------------------------
 @float_a    , @float_a=3.14159            3.14159 (Float)
 @float_b    , @float_b = -0.5             -0.5 (Float)
 Product:    , @float_a * @float_b         -1.570795 (Float)

Rational examples:
-----------------------------------------------------------------
 @rational_a , @rational_a = Rational(2,3) 2/3 (Rational)
 @rational_b , @rational_b = 5r            5/1 (Rational)
 Sum:        , @rational_a + @rational_b   17/3 (Rational)

Complex examples:
-----------------------------------------------------------------
 @complex_a  , @complex_a = Complex(2,3)   2+3i (Complex)
 @complex_b  , @complex_b = 4 + 5i         4+5i (Complex)
 Sum:        , @complex_a + @complex_b     6+8i (Complex)

Type conversions:
-----------------------------------------------------------------
 Int2Float:  , @int_a.to_f                 42.0 (Float)
 Float2Int   , @float_a.to_i               3 (Integer)
 Int2Rational, @int_a.to_r                 42/1 (Rational)
 Int2Complex , @int_a.to_c                 42+0i (Complex)

Automatic type promotion:
-----------------------------------------------------------------
 Int2Float   , @int_a + @float_a           45.14159 (Float)
 Int2Rational, @int_a + @rational_a        128/3 (Rational)
 Rational2Flt, @rational_a+@float_a        3.8082566666666664 (Float)
 Complex2Int , @complex_a + @int_a         44+3i (Complex)

Edge case: very large integers
-----------------------------------------------------------------
 @bigInt     , @big_int = 10**20           100000000000000000000 (Integer)
 inc(@bigInt), @big_int += 1               100000000000000000001 (Integer)
-----------------------------------------------------------------

Ruby installation

https://www.ruby-lang.org/en/downloads/

  • Install Ruby
  • Install robocop
  • Notepad++

Ruby Cheatsheet

Basics .{scrollable}

  • $ irb: to write ruby in the terminal
  • don’t use ' in ruby, use " instead
  • you can replace most {} with do end and vice versa –– not true for hashes or #{} escapings
  • Best Practice: end names that produce booleans with question mark
  • CRUD: create, read, update, delete
  • [1,2].map(&:to_i)
  • integer: number without decimal
  • float: number with decimal
  • tag your variables:
    • $: global variable
    • @: instance variable
    • @@: class variable
  • 1_000_000: 1000000 –– just easier to read

Vars, Constants, Arrays, Hashes & Symbols

my_variable = “Hello”
my_variable.capitalize! # ! changes the value of the var same as my_name = my_name.capitalize
my_variable ||= "Hi" # ||= is a conditional assignment only set the variable if it was not set before.

Constants

MY_CONSTANT = # something

Arrays

my_array = [a,b,c,d,e]
my_array[1] # b
my_array[2..-1] # c , d , e
multi_d = [[0,1],[0,1]]
[1, 2, 3] << 4 # [1, 2, 3, 4] same as [1, 2, 3].push(4)

Hashes

hash = { "key1" => "value1", "key2" => "value2" } # same as objects in JavaScript
hash = { key1: "value1", key2: "value2" } # the same hash using symbols instead of strings
my_hash = Hash.new # same as my_hash = {} – set a new key like so: pets["Stevie"] = "cat"
pets["key1"] # value1
pets["Stevie"] # cat
my_hash = Hash.new("default value")
hash.select{ |key, value| value > 3 } # selects all keys in hash that have a value greater than 3
hash.each_key { |k| print k, " " } # ==> key1 key2
hash.each_value { |v| print v } # ==> value1value2

my_hash.each_value { |v| print v, " " }
# ==> 1 2 3

Symbols

:symbol # symbol is like an ID in html. :symbol != "symbol"
# Symbols are often used as Hash keys or referencing method names.
# They can not be changed once created. They save memory (only one copy at a given time). Faster.
:test.to_s # converts to "test"
"test".to_sym # converts to :test
"test".intern # :test
# Symbols can be used like this as well:
my_hash = { key: "value", key2: "value" } # is equal to { :key => "value", :key2 => "value" }

Functions to create Arrays

"bla,bla".split(“,”) # takes string and returns an array (here  ["bla","bla"])

Methods

Methods

def greeting(hello, *names) # *names is a split argument, takes several parameters passed in an array 
  return "#{hello}, #{names}"
end

start = greeting("Hi", "Justin", "Maria", "Herbert") # call a method by name

def name(variable=default)
  ### The last line in here gets returned by default
end

Classes

custom objects

class Person # class names are rather written in PascalCase (It is similar to camelCase, but the first letter is capitalized)
  @@count = 0
  attr_reader :name # make it readable
  attr_writer :name # make it writable
  attr_accessor :name # makes it readable and writable

  def Methodname(parameter)
    @classVariable = parameter
    @@count += 1
  end

  def self.show_classVariable
    @classVariable
  end

  def Person.get_counts # is a class method
    return @@count
  end

  private

  def private_method; end # Private methods go here
end

matz = Person.new("Yukihiro")
matz.show_name # Yukihiro

Inheritance

class DerivedClass < Base
  def some_method
    super(optional args) # 
      # Some stuff
    end
  end
end

Modules

module ModuleName 
end

Math::PI # using PI constant from Math module. 

require 'date' # to use external modules.
puts Date.today # 2016-03-18

module Action
  def jump
    @distance = rand(4) + 2
    puts "I jumped forward #{@distance} feet!"
  end
end

class Rabbit
  include Action 
  extend Action 
  attr_reader :name
  def initialize(name)
    @name = name
  end
end

peter = Rabbit.new("Peter")
peter.jump # include
Rabbit.jump # extend

Blocks & Procs

Code Blocks

Blocks are not objects. A block is just a bit of code between do..end or {}. It’s not an object on its own, but it can be passed to methods like .each or .select.

def yield_name(name)
  yield("Kim") # print "My name is Kim. "
  yield(name) # print "My name is Eric. "
end

yield_name("Eric") { |n| print "My name is #{n}. " } 
yield_name("Peter") { |n| print "My name is #{n}. " }

Proc

Saves blocks and are objects. A proc is a saved block we can use over and over.

cube = Proc.new { |x| x ** 3 }
[1, 2, 3].collect!(&cube) # [1, 8, 27]
cube.call 

Lambdas

lambda { |param| block }
multiply = lambda { |x| x * 3 }
y = [1, 2].collect(&multiply) # 3 , 6

Calculation

  • Addition (+)
  • Subtraction (-)
  • Multiplication (*)
  • Division (/)
  • Exponentiation (**)
  • Modulo (%)
  • The concatenation operator (<<)
  • Increment: 1 += 1 <br> (1++ and 1– do not exist in ruby)
  • Concatenation: "A " << "B" (yields) "A B"
  • String/Numerical interpolation: “A #{4} B”

Commenting

# single line comment

=begin
This is indeed
a multiline comment
=end

Conditionals

If

if 1 < 2
  puts “one smaller than two”
elsif 1 > 2 
  puts “elsif”
else
  puts “false”
end

puts "be printed" if true
puts 3 > 4 ? "if true" : "else" 

Unless

unless false
  puts “I’m here”
else
  puts “not here”
end

puts "not printed" unless true

Case

case my_var
  when "some value"
    ###
  when "some other value"
    ###
  else
    ###
end

or

case my_var
  when "some value" then ###
  when "some other value" then ###
  else ###
end

Logical functions

  • &&: and

  • ||: or

  • !: not

  • (x && (y || w)) && z: use parenthesis to combine arguments

  • flexibility in expression

problem = false
print "Good to go!" if !problem 
print "Good to go!" unless problem

Printing & Putting

puts "first line" # puts text in a separate line

print "blank"
puts "test" # Both both on a single line

String Methods

"Hello".length # 5
"Hello#{123}" # Hello123
"Hello".reverse # “olleH”
"Hello".upcase # “HELLO”
"Hello".downcase # “hello”
"hello".capitalize # “Hello”
"Hello".include? "i" # equals to false because there is no i in Hello
"Hello".gsub!(/e/, "o") # Hollo
"1".to_i # transform string to integer –– 1
"test".to_sym # converts to :test
"test".intern # :test
:test.to_s # converts to "test"

User Input

gets # reads a line
gets.chomp # removes new line char

Loops

While loop

i = 1
while i < 11
  puts i
  i = i + 1
end

Until loop

i = 0
until i == 6
  puts i
  i += 1
end

For loop

for i in 1...10 
  puts i
end

Loop iterator

i = 0
loop do
  i += 1
  print "I'm currently number #{i}” 
  break if i > 5
end

Next

for i in 1..5
  next if i % 2 == 0
  print i
end

.each

things.each do |item|
  print “#{item}"
end

on hashes like so:

hashes.each do |x,y|
  print "#{x}: #{y}"
end

.times

10.times do
  print “this text will appear 10 times”
end

.upto / .downto

1.upto(5) { |x| print x, " " }     # 1 2 3 4 5
"a".upto("c") { |x| print x, " " } # a b c

Sorting & Comparing

array = [5,4,1,3,2]
array.sort! # = [1,2,3,4,5] 
"a" <=> "b" # 0 if a = b, 1 if a > b, -1 if a < b
array.sort! { |a, b| b <=> a } # to sort from Z to A 

Table of Contents

1.is_a? Integer # returns true
:1.is_a? Symbol # returns true
"1".is_a? String # returns true
[1,2,3].collect!() # does something to every element (overwrites original with ! mark)
.map() # is the same as .collect
1.2.floor # 1 # rounds down to the nearest integer.
cube.call # call calls procs directly
Time.now # displays the actual time