Ruby: The Language of Happiness

Learn Ruby and Rails for elegant and productive web development


Ruby: The Language of Happiness
1 Loading...

Ruby: The Language of Happiness

Ruby is a dynamic, open source programming language focused on simplicity and productivity. Created by Yukihiro “Matz” Matsumoto in 1995 in Japan, Ruby was designed to make programmers happy, with a natural syntax that reads almost like English.

Ruby Philosophy: “Ruby is designed to make programmers happy.” - Matz. This philosophy is reflected in every aspect of the language.

Distinctive Features

  1. Everything is an Object - Even numbers and booleans are objects
  2. Blocks and Procs - Powerful and elegant closures
  3. Metaprogramming - Code that writes code
  4. Duck Typing - If it walks like a duck and quacks…
  5. DSLs - Ease of creating Domain Specific Languages
  6. Ruby on Rails - Framework that revolutionized web development

Fundamentals

Types and Variables

# Local variables
name = "Maria"
age = 25
height = 1.68
active = true

# Symbols (immutable and unique)
status = :pending
role = :admin

# Arrays
fruits = ["apple", "banana", "orange"]
fruits << "grape"  # Add
fruits.push("strawberry")

# Hashes
user = {
  name: "Maria",
  email: "[email protected]",
  age: 25
}

# Access
user[:name]  # "Maria"
user.fetch(:phone, "Not provided")

# Ranges
numbers = (1..10)
letters = ("a".."z")
numbers.to_a  # [1, 2, 3, ..., 10]

# String interpolation
message = "Hello, #{name}! You are #{age} years old."

Methods and Blocks

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

# Method with default value
def create_user(name, email, active: true)
  { name: name, email: email, active: active }
end

# Method with block
def execute_with_log
  puts "Starting..."
  result = yield
  puts "Finishing..."
  result
end

execute_with_log { 2 + 2 }  # Returns 4

# Blocks with parameters
[1, 2, 3].map { |n| n * 2 }  # [2, 4, 6]

# Procs and Lambdas
double = ->(x) { x * 2 }
double.call(5)  # 10

# Method chaining
result = [1, 2, 3, 4, 5]
  .select { |n| n.even? }
  .map { |n| n * 2 }
  .sum

Classes and Objects

# Basic class
class User
  attr_reader :id, :email
  attr_accessor :name

  def initialize(name, email)
    @id = SecureRandom.uuid
    @name = name
    @email = email
    @active = true
  end

  def greet
    "Hello, #{@name}!"
  end

  def active?
    @active
  end

  def deactivate!
    @active = false
  end
end

# Inheritance
class Admin < User
  attr_reader :permissions

  def initialize(name, email, permissions = [])
    super(name, email)
    @permissions = permissions
  end

  def can?(action)
    permissions.include?(action.to_sym)
  end
end

# Modules (mixins)
module Timestamps
  def touch
    @updated_at = Time.now
  end

  def created_at
    @created_at ||= Time.now
  end
end

class Article
  include Timestamps

  def initialize(title)
    @title = title
  end
end

# Struct for simple classes
Point = Struct.new(:x, :y) do
  def distance_from_origin
    Math.sqrt(x**2 + y**2)
  end
end

Enumerables

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Transformations
doubled = numbers.map { |n| n * 2 }
evens = numbers.select { |n| n.even? }
odds = numbers.reject { |n| n.even? }

# Reductions
sum = numbers.reduce(0) { |acc, n| acc + n }
sum = numbers.sum  # Shortcut

# Searches
first_even = numbers.find { |n| n.even? }
all_even = numbers.all? { |n| n.even? }
any_even = numbers.any? { |n| n.even? }

# Grouping
groups = numbers.group_by { |n| n.even? ? :even : :odd }

# Sorting
users = [
  { name: "Maria", age: 25 },
  { name: "John", age: 30 },
  { name: "Ana", age: 22 }
]

sorted = users.sort_by { |u| u[:age] }
oldest = users.max_by { |u| u[:age] }

Metaprogramming

# Dynamic define_method
class User
  [:admin, :moderator, :editor].each do |role|
    define_method "#{role}?" do
      @role == role
    end
  end
end

# method_missing for proxy
class HashWrapper
  def initialize(hash)
    @hash = hash
  end

  def method_missing(name, *args)
    if @hash.key?(name)
      @hash[name]
    else
      super
    end
  end

  def respond_to_missing?(name, include_private = false)
    @hash.key?(name) || super
  end
end

wrapper = HashWrapper.new(name: "Maria", email: "[email protected]")
wrapper.name  # "Maria"

Essential Ruby on Rails

# Model with validations
class User < ApplicationRecord
  has_many :posts, dependent: :destroy
  belongs_to :company

  validates :name, presence: true, length: { minimum: 2 }
  validates :email, presence: true, uniqueness: true

  scope :active, -> { where(active: true) }
  scope :admins, -> { where(role: :admin) }
end

# RESTful Controller
class UsersController < ApplicationController
  before_action :set_user, only: [:show, :update, :destroy]

  def index
    @users = User.active.includes(:company)
    render json: @users
  end

  def create
    @user = User.new(user_params)
    
    if @user.save
      render json: @user, status: :created
    else
      render json: { errors: @user.errors }, status: :unprocessable_entity
    end
  end

  private

  def set_user
    @user = User.find(params[:id])
  end

  def user_params
    params.require(:user).permit(:name, :email, :company_id)
  end
end

Essential Tools

ToolPurpose
BundlerDependency manager
RailsFull-stack web framework
RSpecTesting framework
RubocopLinter and formatter
PryAdvanced interactive console

Learning Checklist

  • Master blocks, procs, and lambdas
  • Understand modules and mixins
  • Learn Enumerable methods
  • Study metaprogramming
  • Practice with Ruby on Rails
  • Write tests with RSpec
  • Create a REST API

Essential Resources

Quote

“Ruby is simple in appearance, but very complex inside, like the human body.” - Yukihiro Matsumoto


Ruby makes programming a joyful experience. Discover the happiness of coding with Ruby!