Ruby Class vs. Instance Methods: What's the Difference?
There are two types of methods in Ruby, class methods and instance methods.
Instance methods can only be called on instances of a class you initialize.
Class methods are called on classes themselves, not instances.
The difference might sound subtle but whether or not you have to deal with instances will control how to define the method, how you call the method, and what information the method can access in the class.
# class method, we call it on the class itself Car.get_cars(current_user) # instance method, we call available_seats on an instance car = Car.new(miles: 0, seats: 5) car.available_seats
Let's dive deeper.
Instance Methods in Ruby
Instance methods are called on instances or objects of a class.
For example, we might create a
Car class so we can initialize multiple instances of cars. If we want to be able to call a method on each specific Car instance, we might want to define our method as an instance method.
For the record, most of the methods you define within ActiveRecord will be instance methods.
Here is an example of a class with an instance method.
class Car < ApplicationRecord belongs_to :owner has_many :passengers def initialize(miles:, seats:) @miles = miles @seats = seats end # This is an instance method def available_seats @seats - passengers.count end end
Instance methods have the benefit of accessing the instance variables of classes. Because we defined
@seats as an instance variable, our car instance is able to access it in its own instance methods.
A class method wouldn't be able to access the
@seats instance variable of this car.
Class Methods in Ruby
When we want to call a method that doesn't relate to a specific instance, it's best to encapsulate that method as a class method.
An example use case might be, if you want to run a query or fetch all types of cars the meet a certain criteria.
In Ruby on Rails, you might normally write an ActiveRecord query to accomplish this, but for better code organization you should encapsulate complex queries whenever possible into the models they are querying.
Below is an example where we have a query that fetches all instances of our
Car class based on the owner of the car. In order to keep our code DRY and not repeat this query in several places in our codebase, it's best to embed it in our class so we can just reference the class method.
class Car < ApplicationRecord belongs_to :owner has_many :passengers def self.get_cars(owner) # This is a class method Car.includes(:passengers).where(owner: owner).order(created_at: :desc) end end
Now when any part of our application needs to pull this data set, instead of writing out the full query, we can call
We don't have to worry about updating the query in one place and forgetting to update it everywhere else. Plus, testing this will be much easier.
Connecting the Dots
So now we've defined both class and instance methods. In a real application, this means our class definition would contain both types of methods.
In this case, you need to pay attention, particularly to the name of the method. If it begins with
def self as does
def self.get_cars(owner) that implies this method is called on the class itself and not an instantiated class object.
class Car < ApplicationRecord belongs_to :owner has_many :passengers def initialize(miles:, seats:) @miles = miles @seats = seats end # This is an instance method def available_seats seats - passengers.count end def self.get_cars(owner) # This is a class method Car.includes(:passengers).where(owner: owner).order(created_at: :desc) end end
So, what's the difference between these two types of methods? Instance methods are defined inside a particular instance of a class. On the other hand, class methods are defined by the class itself (hence the
def self), and they can only be called on the class itself.
Instance methods are the default, and to create class methods you have to prepend the method name with
self. when defining the class method.
But that's it!
That's the difference between class methods and instance methods, how to define them, and how to call each different method.