Ruby on Rails Tutorial - Essential Syntax and Methods Guide for Beginners

Getting Started with Ruby on Rails: Syntax and Built-in Methods

A comprehensive guide exploring Ruby’s syntax and built-in methods for common data structures, with helpful comparisons to Python.

📚 Official Ruby on Rails Documentation

Table of Contents

  1. Introduction
  2. Class Definitions
  3. Inheritance
  4. Function Definitions
  5. Variables and Scope
  6. Loops and Iteration
  7. Common Default Functions
  8. Built-in Methods

Introduction

If you’re new to Ruby on Rails like me, the initial learning curve might seem steep. However, once you grasp Ruby’s syntax basics, Rails becomes a natural progression. Let’s walk through basic Ruby syntax elements with Python comparisons to help you understand the concepts better. Let’s get started!

Class Definitions

Ruby Syntax

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Person
  def initialize(name, age)
    @name = name  # Instance variable; note that Ruby uses `@` to denote instance variables
    @age = age
  end

  def introduce
    "Hi, my name is #{@name} and I am #{@age} years old."
  end
end

# Usage
person = Person.new("Alice", 30)
puts person.introduce

Python Equivalent

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def introduce(self):
        return f"Hi, my name is {self.name} and I am {self.age} years old."

# Usage
person = Person("Alice", 30)
print(person.introduce())

💡 Key Difference: Ruby uses @ for instance variables, while Python uses self.

Inheritance

Ruby Implementation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Employee < Person
  def initialize(name, age, position)
    super(name, age)  # Calls parent class's constructor
    @position = position  # then we set the instance variable
  end

  def work
    "#{@name} is working as a #{@position}."
  end
end

Python Implementation

1
2
3
4
5
6
7
class Employee(Person):
    def __init__(self, name, age, position):
        super().__init__(name, age)
        self.position = position

    def work(self):
        return f"{self.name} is working as a {self.position}."

💡 Key Difference: Ruby uses < for inheritance, Python uses parentheses.

Function Definitions

Ruby Methods

1
2
3
4
5
6
7
8
9
class Calculator
  def add(a, b = 0)  # Default parameter
    a + b
  end
end

calc = Calculator.new
puts calc.add(5, 10)  # => 15
puts calc.add(7)      # => 7 (uses default value)

Python Methods

1
2
3
4
5
6
7
class Calculator:
    def add(self, a, b=0):  # Default parameter
        return a + b

calc = Calculator()
print(calc.add(5, 10))  # => 15
print(calc.add(7))      # => 7 (uses default value)

Variables and Scope

Ruby Variables

1
2
3
4
5
6
def demonstrate_variables
  local_var = "I am local"           # Local variable
  @instance_var = "Instance scope"   # Instance variable
  @@class_var = "Class scope"        # Class variable
  $global_var = "Global scope"       # Global variable
end

Python Variables

1
2
3
4
5
def demonstrate_variables(self):
    local_var = "I am local"              # Local variable
    self.instance_var = "Instance scope"  # Instance variable
    # Class variables in Python use class namespace
    # Global variables use global keyword

Loops and Iteration

Ruby Loops

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Each iterator
[1, 2, 3].each do |number|
  puts number
end

# For loop
for number in 1..5
  puts number
end

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

# Until loop (Ruby-specific)
i = 0
until i >= 5
  puts i
  i += 1
end

Built-in Methods

String Methods

1
2
3
4
5
6
7
8
# Common string operations
str = "Hello, World!"
str.length      # => 13
str.upcase      # => "HELLO, WORLD!"
str.downcase    # => "hello, world!"
str.capitalize  # => "Hello, world!"
str.reverse     # => "!dlroW ,olleH"
str.split(",")  # => ["Hello", " World!"]

Array Methods

💡 Note: In Ruby (and Rails), arrays are very flexible and can hold objects of different types simultaneously, similar to Python lists (not tuples, since Python tuples are immutable). This flexibility is one of Ruby’s core principles: “everything is an object” and the language tries to be as permissive as possible to make developers’ lives easier.

1
2
3
4
5
6
7
# Mixed type array examples
mixed_array = [1, "hello", 3.14, true, [1, 2], {name: "John"}]
# You can add different types at any time
mixed_array.push(:symbol)  # Adds a Symbol
mixed_array << nil        # Adds nil using the shovel operator
mixed_array.unshift(42.0) # Adds a Float at the beginning
# All valid operations!
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Array operations
arr = [1, 2, 3, 4, 5]
arr.length        # => 5
arr.first        # => 1
arr.last         # => 5
arr.push(6)      # => [1, 2, 3, 4, 5, 6]
arr.pop          # => 6
arr.include?(3)  # => true

# how to insert an element at the beginning of the array
arr.unshift(0)   # => [0, 1, 2, 3, 4, 5]

# how to insert an element at the end of the array
arr.push(6)      # => [0, 1, 2, 3, 4, 5, 6]

# how to insert an element at a specific index
arr.insert(0, 0) # => [0, 0, 1, 2, 3, 4, 5]

# how to remove an element at a specific index
arr.delete_at(0) # => [0, 1, 2, 3, 4, 5]

# how to remove an element at a specific **value**
arr.delete(0) # => [1, 2, 3, 4, 5]

# how to remove all elements from the array that satisfy the condition
arr.delete_if { |n| n.even? } # => [1, 3, 5]  # Removes all elements that satisfy the condition

# how to remove all elements from the array
arr.clear # => []

# how to remove the first element from the array and return the removed element
arr.shift # => [0]  # Removes the first element from the array and returns it

# how to insert an element at the beginning of the array
arr.unshift(-1) # => [0, 0, 1, 2, 3, 4, 5]
arr.unshift("a" , "b") # => ["a", "b", 0, 0, 1, 2, 3, 4, 5]

# how to remove the last element from the array and return the removed element
arr.pop # => [5]  # Removes the last element from the array and returns it

Hash Methods

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# Hash operations
hash = { name: "John", age: 30 }
hash.keys           # => [:name, :age]
hash.values        # => ["John", 30]
hash[:name]        # => "John"
hash.merge(city: "New York") # => {:name=>"John", :age=>30, :city=>"New York"}
hash.delete(:age) # => 30  # Deletes the key-value pair with the specified key and returns the value that was deleted

# Remove key-value pairs based on a condition
hash = { name: "John", age: 30, role: "Developer", level: "Senior" }
hash.delete_if { |k,v| v == "John" }  # => {:age=>30, :role=>"Developer", :level=>"Senior"}  # Removes all pairs where value is "John"

# Remove nil values from hash
hash = { name: "John", age: 30, title: nil, department: nil }
hash.compact     # => {:name=>"John", :age=>30}  # Returns new hash with nil values removed
hash.compact!    # Removes nil values from original hash permanently

# how to remove all key-value pairs from the hash
hash.clear # => {}  # Removes all key-value pairs from the hash

Numeric Methods

1
2
3
4
5
6
7
8
# Numeric operations
num = 42
num.even?      # => true
num.odd?       # => false
(-num).abs       # => 42  # The - operator negates num to -42, then abs returns absolute value back to 42
3.14.round     # => 3
3.14.ceil      # => 4
3.14.floor     # => 3

Enumerable Methods

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Collection operations
numbers = [1, 2, 3, 4, 5]

# Map/Collect
numbers.map { |n| n * 2 }      # => [2, 4, 6, 8, 10]  # |n| is a block parameter, similar to a function parameter
                               # It represents each element from 'numbers' as the map iterates
                               # You can name it anything, e.g. |num| or |x|

# Select/Filter
numbers.select { |n| n.even? }  # => [2, 4]

# Reduce/Inject
numbers.reduce(:+)              # => 15  # Adds all numbers in array: 1 + 2 + 3 + 4 + 5 = 15
numbers.inject(:+)              # => 15  # Same as reduce
numbers.inject(0) { |result, element| result + element }  # => 15  # More explicit version where:
                               # - 0 is the initial value
                               # - result is always the accumulated value from previous iterations
                               # - element is the current array element being processed
                               # The block parameters |result, element| follow a convention:
                               # - First parameter is always the accumulator/result
                               # - Second parameter is always the current element

# Sort
numbers.sort                    # => [1, 2, 3, 4, 5]  # Sorts numbers in ascending order (they are sorted already... but you get the point)
numbers.sort.reverse            # => [5, 4, 3, 2, 1]  # Sorts numbers in descending order

# Reverse
numbers.reverse                 # => [5, 4, 3, 2, 1]  # Reverses the order of the array

# First/Last
numbers.first                   # => 1  # Returns the first element of the array

# Any/All
numbers.any? { |n| n > 3 }     # => true  # Returns true because at least one number (4,5) is greater than 3
numbers.all? { |n| n < 6 }     # => true  # Returns true because every number (1,2,3,4,5) is less than 6

Cheers! 🍺