iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

self & Class Methods

Ruby self: who am I? Instance vs class context, defining class methods, and the subtle rules around self.

Ruby — self

EXAMPLE
# ===== In an instance method =====
class User
  attr_accessor :name

  def initialize(name)
    @name = name
  end

  def greet
    # self refers to the current instance
    "Hi from #{self.name}"   # or just 'name' since attr_accessor exposes it
  end
end

User.new('Alex').greet   # 'Hi from Alex'

# ===== self= setter requires explicit self ===== =====
class User
  attr_accessor :name
  def rename(new_name)
    self.name = new_name   # self. is REQUIRED for the setter
    # name = new_name      # creates a LOCAL variable, doesn't call name=
  end
end

# ===== Class-level: self IS the class =====
class User
  puts self    # User
  def self.create(name)
    new(name)   # equivalent to User.new(name)
  end
end

User.create('Alex')

# ===== Defining class methods =====
# Three styles:

# 1. def self.method
class Service
  def self.start; end
end

# 2. class << self ... end (singleton class)
class Service
  class << self
    def start; end
    def stop; end
  end
end

# 3. Module#module_function (works for modules being mixed in)

# ===== Inside class << self =====
class Service
  class << self
    attr_accessor :registry
  end
end
Service.registry = {}

# ===== self vs nil =====
# self is never nil inside a method body.
# But in main scope, self is the 'main' object:
puts self    # main

# ===== Why does it matter =====
# 1. Distinguishing instance methods (def x) from class methods (def self.x)
# 2. Using setters requires explicit self.
# 3. Block context: self inside a block is usually the enclosing self,
#    UNLESS instance_exec changes it.

# ===== Block context manipulation =====
class Config
  def self.configure(&block)
    instance_eval(&block)   # 'self' inside block becomes the Config class
  end
end

Config.configure do
  puts self    # Config
end

# Rake / DSL style libraries lean on this.

# ===== Singleton methods (per-object) =====
str = 'hello'
def str.shout
  upcase + '!'
end
str.shout      # 'HELLO!'
# But 'world'.shout would error — singleton method only on this object.

# ===== Patterns to internalise =====
# - def self.method for class methods
# - self.attr = ... when calling a setter
# - instance_eval / instance_exec for DSL contexts
# - Avoid singleton methods on objects from outside; surprising for readers

# ===== Pitfalls =====
# - 'name = value' inside an instance method creates a LOCAL variable, not calling name=
# - Confusing class scope (where self is the class) with instance scope
# - Defining 'def method' inside class << self vs def self.method (both work; pick one for the team)
# - Forgetting that 'self' inside a Proc/Lambda is the enclosing context, not the method's receiver

Why it matters

self is who-am-I at this point. In instance methods, it is the instance. In class scope, it is the class. Setters always need explicit self. — local variables silently shadow them otherwise. DSLs lean on instance_eval to change self deliberately; for everyday code, the explicit forms are clearest.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
class Counter
    def self.create = new(0)   # class method
    def initialize(start) = @n = start
end
Try it Yourself »

Discussion

Loading…