Skip
Arish's avatar

13. Classes and Objects


Classes and Objects in Ruby

Ruby is a pure object-oriented language - everything is an object! Understanding classes and objects is essential for mastering Rails, where models, controllers, and everything else are classes.

Creating a Class

ruby
1class User
2  # Class body
3end
4
5# Creating an instance (object)
6user = User.new

Instance Variables and Methods

ruby
1class User
2  # Initialize method (constructor)
3  def initialize(name, email)
4    @name = name    # Instance variable
5    @email = email  # Instance variable
6  end
7  
8  # Instance method
9  def greet
10    "Hello, I'm #{@name}!"
11  end
12  
13  # Getter method
14  def name
15    @name
16  end
17  
18  # Setter method
19  def name=(new_name)
20    @name = new_name
21  end
22end
23
24user = User.new("John", "john@example.com")
25user.greet        # => "Hello, I'm John!"
26user.name         # => "John"
27user.name = "Jane"
28user.name         # => "Jane"

Attribute Accessors

Ruby provides shortcuts for getters and setters:

ruby
1class User
2  # Creates getter and setter for name and email
3  attr_accessor :name, :email
4  
5  # Creates only getter
6  attr_reader :created_at
7  
8  # Creates only setter
9  attr_writer :password
10  
11  def initialize(name, email)
12    @name = name
13    @email = email
14    @created_at = Time.now
15  end
16end
17
18user = User.new("John", "john@example.com")
19user.name           # => "John" (getter)
20user.name = "Jane"  # Setter
21user.created_at     # => 2024-01-15 10:30:00 (read-only)
22user.password = "secret"  # Write-only

Class Methods and Variables

ruby
1class User
2  # Class variable (shared across all instances)
3  @@count = 0
4  
5  def initialize(name)
6    @name = name
7    @@count += 1
8  end
9  
10  # Class method
11  def self.count
12    @@count
13  end
14  
15  # Alternative syntax for class methods
16  class << self
17    def description
18      "A user in the system"
19    end
20  end
21end
22
23User.new("John")
24User.new("Jane")
25User.count        # => 2
26User.description  # => "A user in the system"

Inheritance

ruby
1class Animal
2  attr_accessor :name
3  
4  def initialize(name)
5    @name = name
6  end
7  
8  def speak
9    "Some sound"
10  end
11end
12
13class Dog < Animal
14  def speak
15    "Woof!"
16  end
17  
18  def fetch
19    "#{@name} is fetching the ball!"
20  end
21end
22
23class Cat < Animal
24  def speak
25    "Meow!"
26  end
27end
28
29dog = Dog.new("Buddy")
30dog.speak   # => "Woof!"
31dog.fetch   # => "Buddy is fetching the ball!"
32dog.name    # => "Buddy" (inherited from Animal)
33
34cat = Cat.new("Whiskers")
35cat.speak   # => "Meow!"

Super Keyword

Call the parent class method:

ruby
1class Animal
2  def initialize(name)
3    @name = name
4  end
5  
6  def info
7    "Name: #{@name}"
8  end
9end
10
11class Dog < Animal
12  def initialize(name, breed)
13    super(name)  # Call parent's initialize
14    @breed = breed
15  end
16  
17  def info
18    "#{super}, Breed: #{@breed}"  # Call parent's info
19  end
20end
21
22dog = Dog.new("Buddy", "Golden Retriever")
23dog.info  # => "Name: Buddy, Breed: Golden Retriever"

Modules and Mixins

Modules let you share code between classes:

ruby
1# Module for shared behavior
2module Printable
3  def print_info
4    puts "Printing #{self.class.name} information..."
5    instance_variables.each do |var|
6      puts "#{var}: #{instance_variable_get(var)}"
7    end
8  end
9end
10
11module Timestampable
12  def created_at
13    @created_at ||= Time.now
14  end
15  
16  def updated_at
17    @updated_at
18  end
19  
20  def touch
21    @updated_at = Time.now
22  end
23end
24
25class User
26  include Printable      # Include as instance methods
27  include Timestampable
28  
29  attr_accessor :name, :email
30  
31  def initialize(name, email)
32    @name = name
33    @email = email
34  end
35end
36
37user = User.new("John", "john@example.com")
38user.print_info
39user.created_at
40user.touch

Include vs Extend

ruby
1module Greetable
2  def greet
3    "Hello!"
4  end
5end
6
7class User
8  include Greetable  # Adds as instance methods
9end
10
11class Admin
12  extend Greetable   # Adds as class methods
13end
14
15User.new.greet   # => "Hello!" (instance method)
16Admin.greet      # => "Hello!" (class method)

Namespacing with Modules

ruby
1module Admin
2  class User
3    def role
4      "admin"
5    end
6  end
7end
8
9module Public
10  class User
11    def role
12      "public"
13    end
14  end
15end
16
17Admin::User.new.role   # => "admin"
18Public::User.new.role  # => "public"

Object Comparison

ruby
1class User
2  attr_reader :id, :name
3  
4  def initialize(id, name)
5    @id = id
6    @name = name
7  end
8  
9  # Compare by ID
10  def ==(other)
11    self.class == other.class && id == other.id
12  end
13  
14  # For use in hashes
15  def eql?(other)
16    self == other
17  end
18  
19  def hash
20    id.hash
21  end
22end
23
24user1 = User.new(1, "John")
25user2 = User.new(1, "John Doe")
26user3 = User.new(2, "Jane")
27
28user1 == user2  # => true (same ID)
29user1 == user3  # => false (different ID)

Struct (Quick Classes)

For simple data objects:

ruby
1# Quick way to create a class
2User = Struct.new(:name, :email) do
3  def greeting
4    "Hello, #{name}!"
5  end
6end
7
8user = User.new("John", "john@example.com")
9user.name      # => "John"
10user.greeting  # => "Hello, John!"
11
12# Keyword arguments version
13User = Struct.new(:name, :email, keyword_init: true)
14user = User.new(name: "John", email: "john@example.com")

Ruby Object Hierarchy

ruby
1# Everything inherits from Object
2class User
3end
4
5User.ancestors
6# => [User, Object, Kernel, BasicObject]
7
8# Check inheritance
9User.superclass        # => Object
101.class                # => Integer
111.class.superclass     # => Numeric
12"hello".class          # => String
13[].class               # => Array
14{}.class               # => Hash
15
16# Check if object is an instance
17user = User.new
18user.is_a?(User)       # => true
19user.is_a?(Object)     # => true
20user.instance_of?(User)  # => true (exact class only)

Classes and objects form the foundation of Ruby. Rails uses these concepts everywhere - from models to controllers to views!