Skip to content

Ruby

Breakdown of Ruby Syntax

Ruby is a dynamic, open-source, object-oriented programming language known for its simplicity and elegance. It was designed with an emphasis on developer happiness and productivity. Ruby is widely used for web development, particularly with the Ruby on Rails framework.


1. Basic Structure of a Ruby Program

A basic Ruby program typically consists of functions and classes, and the syntax is clean and minimal.

puts "Hello, World!"
  • puts: A method that prints a string to the console, followed by a new line.
  • Ruby doesn't need explicit declaration of entry points (like main in other languages). You just run the script.

2. Variables and Data Types

Ruby uses dynamic typing, meaning variables don’t need explicit type declarations.

Variables

name = "Alice"     # String
age = 25           # Integer
height = 5.5       # Float
is_active = true   # Boolean
  • Variables are assigned without type declarations. The interpreter determines the type.
  • Ruby uses snake_case for variable names.

Data Types

string = "Hello"  # String
integer = 10      # Integer
float = 10.5      # Float
boolean = true    # Boolean
array = [1, 2, 3] # Array
hash = { name: "Alice", age: 25 }  # Hash (key-value pairs)
  • String: Sequences of characters.
  • Integer: Whole numbers.
  • Float: Decimal numbers.
  • Boolean: true or false.
  • Array: Ordered collection of items.
  • Hash: Collection of key-value pairs, similar to a dictionary.

3. Methods

Ruby uses methods to define functions, and they are invoked with arguments. Methods are defined using the def keyword.

def greet(name)
  puts "Hello, #{name}!"
end

greet("Alice")  # Calling the method
  • def: Defines a method.
  • end: Marks the end of a method (and most other blocks).
  • String interpolation: #{} inside a string allows embedding variable values.

Return Values

By default, the last evaluated expression is returned from a method.

def add(a, b)
  a + b
end

result = add(5, 10)
puts result  # 15

4. Control Flow

Ruby has standard control flow constructs like if, unless, case, and loops.

Conditional Statements

x = 10
if x > 5
  puts "Greater than 5"
elsif x == 5
  puts "Equal to 5"
else
  puts "Less than 5"
end
  • if, elsif, else: Conditional statements. elsif is Ruby's version of else if.

Ternary Operator

x = 10
puts x > 5 ? "Greater than 5" : "Less than or equal to 5"
  • Ternary operator: One-line shorthand for if-else.

Loops

# While loop
i = 0
while i < 5
  puts i
  i += 1
end

# For loop (iterates over a range)
for i in 0..4
  puts i
end

# Times loop (repeats a block n times)
5.times { |i| puts i }
  • while: Loops as long as the condition is true.
  • for: Iterates over a collection, range, or array.
  • times: Repeats the block a specified number of times.

Break and Next

# Break exits the loop
for i in 0..5
  break if i == 3
  puts i
end

# Next skips the current iteration
for i in 0..5
  next if i == 3
  puts i
end
  • break: Exits the loop.
  • next: Skips the current iteration and moves to the next one.

5. Classes and Objects

Ruby is object-oriented, and everything in Ruby is an object, including numbers and booleans.

Defining a Class

class Person
  attr_accessor :name, :age  # Creates getter and setter methods

  def initialize(name, age)
    @name = name
    @age = age
  end

  def greet
    puts "Hello, my name is #{@name} and I'm #{@age} years old."
  end
end

person = Person.new("Alice", 25)
person.greet
  • class: Defines a class.
  • attr_accessor: Automatically creates getter and setter methods for instance variables.
  • initialize: Constructor method that is called when a new object is instantiated.
  • @variable: Instance variables (local to an object).
  • new: Used to create a new instance of the class.

1. Basic Class Definition

class Person
  # Class body goes here
end
- class: Keyword to define a class (always PascalCase).
- end: Closes the class definition.


2. Instance Variables & Accessors (Getters/Setters)

Ruby provides shortcuts to generate getters/setters automatically.

(a) Manual Getters/Setters

class Person
  # Constructor (initializes instance variables)
  def initialize(name, age)
    @name = name  # @ denotes instance variables
    @age = age
  end

  # Getter for @name
  def name
    @name
  end

  # Setter for @name (note the '=')
  def name=(new_name)
    @name = new_name
  end

  # Getter for @age
  def age
    @age
  end

  # Setter for @age
  def age=(new_age)
    @age = new_age
  end
end
- @variable: Instance variable (private by default).
- Getter: Method name matches variable (e.g., name).
- Setter: Method name ends with = (e.g., name=).

Ruby provides macros to generate getters/setters:

class Person
  attr_reader :name, :age   # Generates getters
  attr_writer :name, :age   # Generates setters
  attr_accessor :name, :age  # Generates both getters and setters

  def initialize(name, age)
    @name = name
    @age = age
  end
end
- attr_reader: Auto-generates getters.
- attr_writer: Auto-generates setters.
- attr_accessor: Generates both.


3. Constructors (initialize)

Ruby uses initialize as the constructor (called when new is invoked).

class Person
  attr_accessor :name, :age

  # Constructor
  def initialize(name, age)
    @name = name
    @age = age
  end
end

# Usage
person = Person.new("Alice", 30)
puts person.name  # => "Alice" (getter)
person.age = 31   # => 31 (setter)

4. Custom Factory Methods (Class Methods)

Define methods on the class itself (not instances) using self..

class Person
  attr_accessor :name, :age

  def initialize(name, age)
    @name = name
    @age = age
  end

  # Class method (factory)
  def self.from_birth_year(name, birth_year)
    age = Time.now.year - birth_year
    new(name, age)  # Calls initialize
  end
end

# Usage
person = Person.from_birth_year("Bob", 1990)
puts person.age  # => 34 (if current year is 2024)
- self.: Defines a class-level method.
- new: Calls the constructor.


5. Complete Example

Class Definition
class Person
  attr_accessor :name, :age

  # Constructor
  def initialize(name, age)
    @name = name
    @age = age
  end

  # Instance method
  def greet
    puts "Hello, I'm #{@name}!"
  end

  # Class method (factory)
  def self.from_birth_year(name, birth_year)
    age = Time.now.year - birth_year
    new(name, age)
  end
end
Usage
# Default construction
p1 = Person.new("Alice", 25)
p1.greet          # => "Hello, I'm Alice!"
p1.age = 26       # Uses setter

# Factory method
p2 = Person.from_birth_year("Bob", 1990)
puts p2.age       # => 34 (in 2024)

6. Blocks and Procs

Ruby has a powerful block and proc system to pass chunks of code as arguments to methods.

Blocks

def greet(name)
  yield(name)
end

greet("Alice") { |name| puts "Hello, #{name}!" }
  • yield: Invokes the block passed to the method.
  • Blocks are a powerful feature in Ruby, allowing you to write more flexible and reusable code.

Procs (Procedure Objects)

my_proc = Proc.new { |x| puts x * 2 }
my_proc.call(5)  # Outputs 10
  • Proc.new: Defines a proc (a block of code stored as an object).
  • call: Invokes the proc.

Lambdas (Special type of Proc)

my_lambda = ->(x) { puts x * 2 }
my_lambda.call(5)  # Outputs 10
  • ->: Defines a lambda.
  • Lambdas are similar to procs, but they check the number of arguments strictly.

7. Arrays

Arrays are ordered collections of objects.

arr = [1, 2, 3, 4, 5]
puts arr[0]  # Outputs 1
puts arr.length  # Outputs 5

arr.each { |num| puts num * 2 }
  • each: Iterates over the array.
  • []: Accesses an element in the array by index.
  • length: Returns the number of elements in the array.

8. Hashes

Hashes are collections of key-value pairs.

person = { name: "Alice", age: 25 }
puts person[:name]  # Outputs "Alice"
person[:age] = 26   # Modifies the value
  • {}: Defines a hash.
  • []: Accesses the value associated with the key.
  • :key: Symbol keys are commonly used in Ruby.

9. Error Handling

Ruby uses begin-rescue-end blocks to handle exceptions.

begin
  # Code that might raise an error
  1 / 0
rescue ZeroDivisionError => e
  puts "Error: #{e.message}"
else
  puts "No errors"
ensure
  puts "This will always run"
end
  • begin: Starts a block of code that might raise an error.
  • rescue: Catches exceptions and handles them.
  • else: Runs if no error occurs.
  • ensure: Always runs, whether or not an error occurred.

10. Modules

Modules are used for grouping related methods and constants, and they provide mixins (similar to interfaces or abstract classes).

module Greetable
  def greet
    puts "Hello!"
  end
end

class Person
  include Greetable
end

person = Person.new
person.greet  # Outputs "Hello!"
  • module: Defines a module.
  • include: Mixes the module into the class, making its methods available in instances of the class.

Summary of Key Points:

  • Ruby is an object-oriented language with a focus on simplicity and developer happiness.
  • Everything in Ruby is an object, and it uses dynamic typing.
  • Control flow is straightforward, with standard constructs like if, while, for, and blocks.
  • Methods and classes are fundamental to Ruby’s design, with an elegant syntax that minimizes boilerplate.
  • Error handling is clean and efficient with begin-rescue-end blocks.
  • Ruby has powerful features like blocks, procs, and lambdas for functional programming.
  • Modules allow for grouping related functionality and can be used as mixins.

Ruby’s simplicity, along with its powerful object-oriented and functional programming features, makes it a very productive language, especially for web development with frameworks like Ruby on Rails.