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.
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:
- Ruby reads the class definition for
Truck. - It defines a class method called
default_make. - It defines an instance method called
initialize. Truck.newcreates a new instance ofTruck.- During object creation, Ruby automatically calls
initializeon that new instance. - Inside
initialize,selfrefers to the newtruckobject. self.classreturnsTruck.self.class.default_makebecomesTruck.default_make.- The method returns
"mac". @makeis set to"mac".puts truck.makeprintsmac.
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.
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:
selfis the instance insideinitializedefault_makeis 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
| Approach | Example | Works? | Inheritance-friendly? | Notes |
|---|---|---|---|---|
| Hard-coded class name | Truck.default_make | Yes | No | Ties the code to one class |
| Instance calling class dynamically | self.class.default_make | Yes | Yes | Idiomatic for this case |
| Instance-style call | self.default_make | No | No | Looks for an instance method |
| Direct class object in subclass-aware style | self.class | Yes | Yes | Useful 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
@aalways usesTruck@buses the actual class of the instance
Class methods vs instance methods
| Method type | Defined with | Called on | Example |
|---|---|---|---|
| Class method | def self.name | the class | Truck.default_make |
| Instance method | def name | an object instance | truck.make |
Knowing this distinction makes the original question much easier to reason about.
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
selfinside an instance method is the instanceself.classgives 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.
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
- Create a base class with a class method that returns a default value.
- In the instance
initializemethod, read that value without hard-coding the class name. - Add at least one subclass that overrides the class method.
- Store the chosen value in an instance variable.
- Print results to show that each class uses its own default.
Keep learning
Related questions
Add a Default Value to an Existing Column in a Rails Migration
Learn how to add or change a default value on an existing database column using Rails Active Record migrations safely.
Calling an Overridden Monkey-Patched Method in Ruby
Learn how to call the original method when monkey patching in Ruby, including alias_method patterns, examples, pitfalls, and practical usage.
Check Whether a Value Is an Array in Ruby and Count Items
Learn how to test whether a value is an Array in Ruby and count its elements with is_a?, length, size, and count.