Basic Concepts (10 minutes)
Ruby Features
- Dynamic, Interpreted, Object-Oriented
- Everything is an object (including numbers, nil)
- Duck Typing
- Powerful metaprogramming capabilities
Variable Types
local_var = "local" # Local variable
@instance_var = "iv" # Instance variable
@@class_var = "cv" # Class variable
$global_var = "gv" # Global variable
CONSTANT = "const" # Constant
Truthiness and Falsiness
- Only
false
andnil
are false, everything else is true.
Core Syntax (15 minutes)
What are at least three ways to create a class in Ruby?
1. Using the class
keyword
class MyClass
def hello
puts "Hello from MyClass!"
end
end
obj = MyClass.new
obj.hello # Output: "Hello from MyClass!"
2. Using Class.new
MyDynamicClass = Class.new do
def hello
puts "Hello from dynamic class!"
end
end
obj = MyDynamicClass.new
obj.hello # Output: "Hello from dynamic class!"
3. Using Struct
(for quickly creating classes)
Person = Struct.new(:name, :age) do
def greet
puts "Hi, I'm #{name}, aged #{age}!"
end
end
person = Person.new("Alice", 30)
puts person.name # Output: "Alice"
person.greet # Output: "Hi, I'm Alice, aged 30!"
Method Definition
def greet(name = "World")
"Hello, #{name}!"
end
# Method with a block
def with_log
puts "Start"
yield if block_given?
puts "End"
end
Array Operations
%w[a b c] # => ["a", "b", "c"]
[1, 2, 3].map { |x| x * 2 } # => [2, 4, 6]
Object-Oriented Programming (10 minutes)
Classes and Inheritance
class Animal
def speak
"Animal sound"
end
end
class Dog < Animal
def speak
super + ": Woof!"
end
end
Access Control
public
(default)protected
(Methods modified withprotected
can only be called within the instance method definitions of the class itself or its subclasses. Calling them anywhere else will result in an error!)private
(Methods modified withprivate
cannot have an explicit receiver; they can only be called implicitly, withself
as the receiver.)
protected
usage example:
class Person
def initialize(age)
@age = age
end
def older_than?(other_person)
age > other_person.age # Can access other_person's protected method
end
protected
attr_reader :age
end
alice = Person.new(30)
bob = Person.new(25)
puts alice.older_than?(bob) # => true
# bob.age # Would raise NoMethodError (protected method)
class Man < Person
def print_friend_age(man)
puts man.age
end
end
jack = Man.new(43)
jack.print_friend_age(bob) # => 25
Modules and Mixins
module Loggable
def log(msg)
puts "[LOG] #{msg}"
end
end
class Product
include Loggable
end
Advanced Features (10 minutes)
Metaprogramming
# Dynamically define a method
class MyClass
define_method :dynamic_method do |arg|
"Called with #{arg}"
end
end
Method Lookup Path
- Current class → Mixed-in modules (later
include
d modules are checked first) → Parent class
Differences between Proc and Lambda
p = Proc.new { |x, y| [x, y] }
l = lambda { |x, y| [x, y] } # or ->(x,y){ [x,y] }
# Differences: lambda checks the number of arguments, return behavior is different
1. Strictness of Argument Checking
- Lambda: Strictly checks the number of arguments. Throws an
ArgumentError
if they don't match.
lam = lambda { |x, y| [x, y] }
lam.call(1) # ArgumentError: wrong number of arguments (given 1, expected 2)
- Proc: Handles arguments loosely. Missing arguments are assigned
nil
, extra arguments are ignored.
proc = Proc.new { |x, y| [x, y] }
proc.call(1) # [1, nil] (no error)
2. return
Behavior Difference
- Lambda:
return
only exits the current lambda, similar to a method return.
def test_lambda
lam = lambda { return }
lam.call
puts "This line runs!"
end
test_lambda # Outputs "This line runs!"
- Proc:
return
will exit the entire method that contains it.
def test_proc
proc = Proc.new { return }
proc.call
puts "This line never runs!"
end
test_proc # No output (method exits prematurely)