Radical Ruby Online - Welcome!

Radical Ruby Online

Welcome to Radical Ruby Online! The most tubular place on the world wide web to learn the Ruby programming language. Grab your favorite soda, boot up your PC, and let's get coding!

Select a tutorial below to get started:

Notepad - Tutorial1.txt

Tutorial 1: Hello, Ruby!

Ruby is an awesome, object-oriented programming language designed for programmer happiness! Let's start by learning how to display text on the screen, known as "printing" to the console.

Here is the syntax breakdown:

# This is a comment! 
puts "Hello, World!" # This prints the text and moves to the next line

print "This text "
print "will be on the same line."

# The \n is a special character that means "new line"
puts "\nBut this will be on a new line!"

Save this in a file called hello.rb. The .rb extension tells the computer it's a Ruby file. Run it from your MS-DOS prompt or terminal by typing: ruby hello.rb

Back to top

Notepad - Tutorial2.txt

Tutorial 2: Variables & Data Types

Variables are named containers used to save data. To create one, you write a name, an equals sign =, and the data you want to store. Unlike some languages, Ruby uses "Dynamic Typing", meaning you don't have to announce what kind of data the variable will hold.

# STRINGS: Text wrapped in quotes
name = "Radical Surfer"

# INTEGERS: Whole numbers (no decimals, no quotes!)
age = 15

# FLOATS: Numbers with decimal points
high_score = 999.99

# BOOLEANS: Simply 'true' or 'false'
is_cool = true

# ARRAYS: A list of items wrapped in square brackets [] and separated by commas
inventory = ["CD Player", "Skateboard", "Pager"]

# HASHES: A dictionary mapping 'Keys' to 'Values' using =>
stats = { "speed" => 90, "power" => 100 }

# STRING INTERPOLATION: 
# If you put #{variable_name} inside a double-quoted string, 
# Ruby replaces it with the variable's actual value!
puts "My name is #{name} and I am #{age} years old."

# ARRAY ACCESS:
# You can get a specific item from an array using its index number in brackets.
# CRITICAL: Computers start counting at 0, not 1!
puts "My first inventory item is my #{inventory[0]}!" # Prints "CD Player"

Back to top

Notepad - Tutorial3.txt

Tutorial 3: Control Flow & Loops

Programs need to make logic-based decisions and repeat actions. For decisions, we use if blocks. Every if block must be closed with the word end.

password = "admin"

# IF STATEMENT SYNTAX:
# == checks if two things are EXACTLY equal (Warning: = is for assigning variables, == is for comparing!)
if password == "admin"
  puts "Access Granted."
elsif password == "guest" # 'elsif' provides an alternative condition
  puts "Access Limited."
else # 'else' is the catch-all if nothing above was true
  puts "Access Denied."
end

# The 'unless' keyword is literally just 'if not'. It's great for readability!
unless password == "admin"
  puts "Alert! Unauthorized user!"
end

To repeat code, Ruby uses "Loops" and "Blocks". A block is a chunk of code wrapped in either do ... end (for multi-line blocks) or curly braces { ... } (for single-line blocks).

# The .times method repeats the block exactly that many times.
3.times do
  puts "Downloading more RAM..."
end

# The .each method steps through an array one by one.
games = ["Doom", "Quake", "Myst"]
# The variable inside pipes |game| represents the current item in the loop.
games.each do |game|
  puts "Currently playing: #{game}"
end

Back to top

Notepad - Tutorial4.txt

Tutorial 4: Methods

Methods (often called functions) are named, reusable blocks of code. You define them using the def keyword, followed by the method's name, and optionally, variables it should accept (called arguments) in parentheses.

# METHOD SYNTAX:
# 'def' starts it. 'person' and 'mood' are the arguments we are passing in.
# mood = "bodacious" provides a default value if the user forgets to supply one!
def greet(person, mood = "bodacious")
  # IMPLICIT RETURN:
  # In Ruby, you don't need to type the word 'return'. 
  # Whatever the last line of the method evaluates to is sent back automatically!
  "What's up, #{person}? You're looking #{mood} today!"
end # Always close your method with 'end'

# Calling the method:
# Here we provide just the 'person'. It uses the default mood.
puts greet("Dude") 

# Here we provide both, overriding the default mood!
puts greet("Keanu", "excellent")

Back to top

Notepad - Tutorial5.txt

Tutorial 5: Building a CLI Calculator

Let's use user input! We use gets to "get" a string from the user. However, when a user types a number and hits "Enter", the "Enter" keypress is captured as a newline character (\n). The .chomp method literally bites off that invisible newline character at the end!

# 'loop do' creates an infinite loop. It will run forever until it hits a 'break'.
loop do
  puts "Enter first number:"
  # We use .to_f to convert the String input into a Float (a decimal number).
  num1 = gets.chomp.to_f

  puts "Enter second number:"
  num2 = gets.chomp.to_f

  puts "Choose operation (+, -, *, /) OR 'quit':"
  # We leave this as a string, because we are looking for letters/symbols.
  op = gets.chomp

  # Break immediately stops the loop. 
  # .downcase converts their text to lowercase to prevent capitalization bugs.
  break if op.downcase == 'quit'

  # A Case Statement acts like a super-powered 'if/elsif' chain.
  result = case op
    when "+" then num1 + num2
    when "-" then num1 - num2
    when "*" then num1 * num2
    when "/" 
      # THE TERNARY OPERATOR: (condition ? if_true : if_false)
      # It's a 1-line 'if/else' statement!
      num2 == 0 ? "You can't divide by zero, dude!" : num1 / num2
    else "Bogus operation!"
  end

  puts "RESULT: #{result}"
end

Back to top

Notepad - Tutorial6.txt

Tutorial 6: Arrays & Enumerables

Ruby is famous for "Enumerables"—powerful methods attached to Arrays and Hashes that let you change lists of data fast. Here we introduce single-line blocks using curly braces { |variable| code }.

mixtape = ["Smells Like Teen Spirit", "Wonderwall", "Creep", "Loser"]

# THE MAP METHOD:
# .map goes through every item, runs the block, and spits out a BRAND NEW ARRAY 
# with the altered results. Here, .upcase capitalizes every letter.
shouting_mixtape = mixtape.map { |song| song.upcase }

# THE SELECT METHOD:
# .select goes through every item and asks "Is this true?"
# If the code inside the block results in 'true', it keeps the item.
long_titles = mixtape.select { |song| song.length > 5 }

puts "Shouting: #{shouting_mixtape}"
puts "Long titles: #{long_titles}"

Back to top

Notepad - Tutorial7.txt

Tutorial 7: Hashes & Symbols

A Hash is like a real-world dictionary: you look up a word (the Key) to find its definition (the Value). In Ruby, we frequently use Symbols for the Keys.

What is a Symbol? Unlike a String ("name") which requires memory to be allocated every single time you type it, a Symbol (:name) starts with a colon and is stored in memory exactly once. It is incredibly fast and efficient for labeling data!

# OLD-SCHOOL HASH SYNTAX (Using the Hash Rocket =>)
user_profile = {
  :username => "CyberPunk99",
  :level => 42
}

# MODERN HASH SYNTAX (Looks like JSON from JavaScript!)
# Notice the colon moved to the right side of the word. Under the hood, this is still a Symbol!
modern_profile = {
  username: "NetSurfer",
  level: 10,
  status: "Offline"
}

# To grab a value, put the Symbol Key inside square brackets:
puts "User: #{modern_profile[:username]}" # Outputs "NetSurfer"

Back to top

Notepad - Tutorial8.txt

Tutorial 8: Classes & Objects

In Object-Oriented Programming (OOP), you build digital blueprints called Classes. From those blueprints, you create real, usable Instances (objects).

# Define a blueprint with the 'class' keyword. Class names ALWAYS start with a Capital Letter.
class Tamagotchi
  # attr_accessor is a Ruby magic trick! 
  # It automatically allows us to read and write to the @name and @hunger variables from outside the class.
  attr_accessor :name, :hunger

  # The 'initialize' method is unique. 
  # The instant you type .new on your class, this method triggers to set up the object.
  def initialize(name)
    # The @ symbol creates an "Instance Variable". 
    # Normal variables die when a method ends. Instance variables live as long as the object lives!
    @name = name 
    @hunger = 50
  end

  # A custom method specific to Tamagotchis
  def feed
    @hunger -= 10 # This is shorthand for @hunger = @hunger - 10
    puts "#{@name} says: YUM! Hunger is down to #{@hunger}."
  end
end

# We use the blueprint to construct a real object using .new
pet = Tamagotchi.new("Dino")
# We call methods on the object using a dot!
pet.feed

Back to top

Notepad - Tutorial9.txt

Tutorial 9: File I/O

Storing text to a user's hard drive requires File Input/Output (I/O). You do this using the built-in File class.

# WRITING TO A FILE:
# We open "secret.txt". The "w" mode stands for "Write" (it will create the file, or OVERWRITE it completely).
# Providing a block (do |file|) is good practice because Ruby will automatically securely close the file when the block ends!
File.open("secret.txt", "w") do |file|
  # We use the variable we defined in the block '|file|' to refer to our opened document.
  file.puts "Hack the planet!"
end

# READING FROM A FILE:
# File.exist? prevents our application from crashing by checking if the file is truly there.
if File.exist?("secret.txt")
  # File.read slaps the entire contents of the text file directly into the 'contents' string variable.
  contents = File.read("secret.txt")
  puts "File contents: #{contents}"
end

Back to top

Notepad - Tutorial10.txt

Tutorial 10: To-Do List App

Let's look at advanced syntax chaining to build a real app that remembers your notes!

todos = []

if File.exist?("todos.txt")
  # File.readlines turns every line of the text file into an item in an array.
  # .map(&:chomp) is advanced shorthand syntax! It applies the .chomp method 
  # to every item in the array to strip away the \n linebreaks.
  todos = File.readlines("todos.txt").map(&:chomp)
end

loop do
  puts "\n--- YOUR TO-DOS ---"
  # each_with_index is an enumerable that gives you both the item (task) AND its number (i)
  todos.each_with_index { |task, i| puts "#{i + 1}. #{task}" }
  
  puts "Type 'add [task]', 'done [number]', or 'exit'"

  # .split(" ", 2) takes what the user typed and chops it into an array of two pieces at the first space.
  # Ex: "add go shopping" becomes => ["add", "go shopping"]
  input = gets.chomp.split(" ", 2) 
  command = input[0].downcase

  case command
  when 'add'
    # The shovel operator << "shovels" an item onto the very end of an Array. Super fast!
    todos << input[1] 
  when 'done'
    # .to_i converts the user's string ("1") into an Integer (1). We subtract 1 because Arrays start at 0!
    index = input[1].to_i - 1
    todos.delete_at(index) if index >= 0 # Only delete if the math isn't negative
  when 'exit'
    break # Leave the loop
  end
end

# Save the altered Array back into the hard drive before the program shuts down.
File.open("todos.txt", "w") do |f|
  todos.each { |task| f.puts(task) }
end
puts "Saved! Catch ya later."

Back to top