Question

Calling a Class Method from an Instance in Ruby

rubyclass-method

Question

In Ruby, how can you call a class method from one of that class's instances without hard-coding the class name?

For example:

class Truck
  def self.default_make
    "mac"
  end

  def initialize
    Truck.default_make
  end
end

Here, Truck.default_make works, but it repeats the class name inside the class definition. Is there a more idiomatic Ruby way to call that class method from an instance method, especially if you want to avoid explicitly writing Truck?

Short Answer

By the end of this page, you'll understand the difference between class methods and instance methods in Ruby, how an instance can refer back to its class, and the idiomatic way to call a class method from inside an instance method using self.class.

Concept

In Ruby, class methods belong to the class itself, while instance methods belong to objects created from that class.

In your example:

class Truck
  def self.default_make
    "mac"
  end
end

default_make is a class method, so it is called on Truck, not on an individual truck object.

An instance method like initialize runs in the context of a specific object. Inside that method, self refers to the instance, not the class. That means calling:

self.default_make

would try to find an instance method named default_make, which is not the same thing.

To get from an instance back to its class, Ruby gives you:

self.class

So the idiomatic way to call the class method is:

self.class.default_make

This matters because it keeps your code:

  • more reusable
  • easier to subclass
  • less tightly coupled to a specific class name

If you hard-code Truck.default_make, then subclasses may not behave the way you expect. If you use self.class.default_make, Ruby will call the method on the actual runtime class of the object.

Mental Model

Think of a class as a blueprint and an instance as a specific item built from that blueprint.

  • The class method is information written on the blueprint.
  • The instance method is behavior of the actual item.

If the item needs to read something from its blueprint, it can ask:

self.class

That means: "What blueprint was I made from?"

Then it can read the class method from that blueprint:

self.class.default_make

So instead of saying, "Go to the Truck blueprint," the object says, "Go to my blueprint." That is more flexible.

Take Quiz

Syntax and Examples

The core pattern is:

self.class.class_method_name

Basic example

class Truck
  def self.default_make
    "mac"
  end

  def initialize
    @make = self.class.default_make
  end

  attr_reader :make
end

truck = Truck.new
puts truck.make

Output:

mac

Why not use self.default_make?

Because inside an instance method, self is the object instance:

class Truck
  def self.default_make
    "mac"
  end

  def initialize
    self.default_make
  end
end

This raises an error because default_make is not an instance method.

Subclass-friendly example

class Truck
  def self.default_make
    "mac"
  end

  def initialize
    @make = self.class.default_make
  end

  attr_reader :make
end

class Pickup < Truck
  def self.default_make
    "ford"
  end
end

puts Truck.new.make
puts Pickup.new.make

Output:

mac
ford

This is one of the biggest benefits of self.class: it respects inheritance.

Step by Step Execution

Consider this example:

class Truck
  def self.default_make
    "mac"
  end

  def initialize
    @make = self.class.default_make
  end

  attr_reader :make
end

truck = Truck.new
puts truck.make

Step by step:

  1. Ruby reads the class definition for Truck.
  2. It defines a class method called default_make.
  3. It defines an instance method called initialize.
  4. Truck.new creates a new instance of Truck.
  5. During object creation, Ruby automatically calls initialize on that new instance.
  6. Inside initialize, self refers to the new truck object.
  7. self.class returns Truck.
  8. self.class.default_make becomes Truck.default_make.
  9. The method returns "mac".
  10. @make is set to "mac".
  11. puts truck.make prints mac.

Trace version

class Truck
  def self.default_make
    puts "Calling class method"
    "mac"
  end

  def initialize
    puts "self is: #{self.inspect}"
    puts "self.class is: #{self.class}"
    @make = self.class.default_make
  end
end

Truck.new

Typical output:

self is: #<Truck:0x000...>
self.class is: Truck
Calling class method

This shows clearly that self is the instance, and self.class is the class object.

Real World Use Cases

Calling class methods from instances is useful when instances need access to class-level configuration or defaults.

Common scenarios

  • Default configuration

    class ApiClient
      def self.default_timeout
        30
      end
    
      def initialize
        @timeout = self.class.default_timeout
      end
    end
    
  • Per-class defaults in inheritance hierarchies

    class Vehicle
      def self.category
        "generic"
      end
    
      def category
        self.class.category
      end
    end
    
    class Bike < Vehicle
      def self.category
        "two-wheeler"
      end
    end
    
  • ORM or framework metadata An instance may ask its class for table names, API endpoints, or validation rules.

  • Factory-like behavior An instance can initialize itself using class-level constants or helper methods exposed as class methods.

These patterns appear in apps, libraries, and frameworks whenever instance behavior depends on class-specific settings.

Take Quiz

Real Codebase Usage

In real Ruby codebases, developers often use self.class when instance behavior should adapt to the exact class being instantiated.

Common patterns

1. Default values from the class

class Report
  def self.default_format
    :pdf
  end

  def initialize(format = nil)
    @format = format || self.class.default_format
  end
end

2. Inheritance-aware behavior

class Notification
  def self.channel
    :email
  end

  def deliver
    puts "Sending via #{self.class.channel}"
  end
end

class SmsNotification < Notification
  def self.channel
    :sms
  end
end

3. Validation or configuration lookup

class Importer
  def self.supported_types
    ["csv", "json"]
  end

  def valid_type?(type)
    self.class.supported_types.include?(type)
  end
end

Why developers prefer this

  • avoids hard-coded class names
  • works better with subclasses
  • makes refactoring easier
  • reduces duplication

Related pattern: guard clauses

class Importer
  def self.supported_types
    ["csv", "json"]
  end

  def import(type)
    return "Unsupported type" unless self.class.supported_types.include?(type)

    "Importing #{type}"
  end
end

This combines class-level configuration with clean instance-level control flow.

Common Mistakes

Here are common mistakes beginners make when working with class methods and instances in Ruby.

1. Calling a class method as if it were an instance method

Broken code:

class Truck
  def self.default_make
    "mac"
  end

  def initialize
    self.default_make
  end
end

Problem:

  • self is the instance inside initialize
  • default_make is defined on the class

Fix:

def initialize
  self.class.default_make
end

2. Hard-coding the class name unnecessarily

Less flexible:

class Truck
  def self.default_make
    "mac"
  end

  def initialize
    @make = Truck.default_make
  end
end

Problem:

  • works, but tightly couples the code to Truck
  • can cause issues with subclasses

Better:

def initialize
  @make = self.class.default_make
end

3. Confusing class with a keyword for definition only

Some beginners think class is only used when defining classes. But every Ruby object can respond to .class:

puts "hello".class
puts 123.class

4. Expecting private access rules to work the same way

Ruby method lookup and visibility can be confusing. A class method and an instance method are separate methods on separate objects.

5. Forgetting inheritance behavior

If you use Truck.default_make, then a subclass instance may still use Truck's version even when it should use its own.

Example:

class Truck
  def self.default_make
    "mac"
  end

  def initialize
    @make = Truck.default_make
  end

  attr_reader :make
end

class Pickup < Truck
  def self.default_make
    "ford"
  end
end

puts Pickup.new.make

This prints mac, not ford.

Using self.class.default_make avoids that problem.

Comparisons

ApproachExampleWorks?Inheritance-friendly?Notes
Hard-coded class nameTruck.default_makeYesNoTies the code to one class
Instance calling class dynamicallyself.class.default_makeYesYesIdiomatic for this case
Instance-style callself.default_makeNoNoLooks for an instance method
Direct class object in subclass-aware styleself.classYesYesUseful when behavior depends on runtime class

Truck.default_make vs self.class.default_make

class Truck
  def self.default_make
    "mac"
  end

  def initialize
    @a = Truck.default_make
    @b = self.class.default_make
  end
end
  • @a always uses Truck
  • @b uses the actual class of the instance

Class methods vs instance methods

Method typeDefined withCalled onExample
Class methoddef self.namethe classTruck.default_make
Instance methoddef namean object instancetruck.make

Knowing this distinction makes the original question much easier to reason about.

Take Quiz

Cheat Sheet

Core idea

Use this inside an instance method to call a class method:

self.class.some_class_method

Example

class Truck
  def self.default_make
    "mac"
  end

  def initialize
    @make = self.class.default_make
  end
end

Rules to remember

  • self inside an instance method is the instance
  • self.class gives the instance's class
  • class methods are called on the class object
  • instance methods are called on instances

Avoid

self.default_make

unless default_make is also defined as an instance method.

Prefer over hard-coding

Truck.default_make

Use self.class.default_make when you want subclass-friendly behavior.

Good use cases

  • default values
  • per-class configuration
  • inheritance-aware behavior
  • metadata lookup

Edge case

If you specifically want the base class version and do not want subclasses to override it, then hard-coding the class name may be intentional.

FAQ

How do you call a class method from an instance in Ruby?

Use self.class.method_name inside the instance method.

self.class.default_make

Why does self.default_make not work?

Because self inside an instance method refers to the instance object, and Ruby will look for an instance method named default_make.

Is self.class.default_make the Ruby idiom?

Yes, it is the usual way to call a class method dynamically from an instance when you do not want to hard-code the class name.

Should I always avoid writing the class name directly?

Not always. If you intentionally want the exact base class method and do not want subclass overrides, using the class name directly can be acceptable.

Does self.class work for subclasses?

Yes. That is one of its biggest advantages. It returns the actual runtime class of the object.

Can I make the same behavior available as an instance method instead?

Yes. You could define an instance method that delegates to the class method if that makes the API clearer.

def default_make
  self.class.default_make
end

Is initialize a class method?

No. initialize is an instance method that Ruby calls automatically when you create a new object with .new.

Take Quiz

Mini Project

Description

Build a small Ruby class hierarchy for vehicles where each class provides its own default brand as a class method, and each instance reads that value during initialization. This demonstrates how self.class keeps instance code flexible and inheritance-friendly.

Goal

Create instances that automatically use the correct class-level default value without hard-coding the class name.

Requirements

  1. Create a base class with a class method that returns a default value.
  2. In the instance initialize method, read that value without hard-coding the class name.
  3. Add at least one subclass that overrides the class method.
  4. Store the chosen value in an instance variable.
  5. Print results to show that each class uses its own default.
Take Quiz

Keep learning

Related questions

View more