Lesson Weekend

Before we build our backend logic for a record store, we'll need to learn about class methods and class variables. In this lesson, we'll cover class methods, then in the next lesson, we'll cover class variables.

Class methods are called on a class, not an instance of an object. They are functionally the same as the static methods we learned about in Intermediate JavaScript. Let's take a look at an example which we can apply later to our record store. Note: Don't add any of this code to your application yet. We're just learning about important concepts here. If you want to try out the following code, use IRB instead.

class Album
  attr_accessor :name

  def initialize(name)
    @name = name
  end
end

Now we can create items and both see and update the name of each item on the list.

> album1 = Album.new("A Love Supreme")
=> #<Album:0x007fc17b12ba30 @name="A Love Supreme">
> album2 = Album.new("Blue")
=> #<Album:0x007fc17b1128c8 @name="Blue">
> album3 = Album.new("In Rainbows")
=> #<Album:0x007fc17b0f95f8 @name="In Rainbows">

We have three albums we can add to our record store. However, we don't have a way to see all of the albums at once. That’s kind of a problem. After all, we want to show a list of albums on our home page.

We need a method that will show all of the items on a list, but an instance method isn't a good way to do this. An instance method is only called on a single instance of an object. An all() method, on the other hand, involves every instance of the object on the list.

Whenever we need a method that should deal with multiple instances of a class, we should use a class method. Here are a few examples of potential class methods we might want in our record store application:

  • all(): returns all albums;
  • find(): finds an album by its name;
  • find_by_ranking(): finds an album by its ranking (if we were to add a rank attribute to our class);
  • top_rated(): finds the top-rated album.

Each of these methods involve access to all albums, not just one. For instance, the find() methods needs to actually be able to look through all albums to find what it’s looking for, so it shouldn’t be an instance method, either. The top_rated() method can only determine which album should be top-rated if it can compare all the albums.

Let's take a look at how to call a class method:

class Album
  ...

  def self.all()
  end

  def self.find(name)
  end

end

There’s really just a small difference between instance methods and class methods. With an instance method, we use:

def method_name()

With a class method, we use:

def self.method_name()

So why do we use the keyword self for class methods? Open up IRB and put in the following code:

class Album
  self
end

The code above will implicitly return the last statement before end, which is self. The value of self is Album. When we're inside a class (but outside of an instance method), the value of self is the class itself. Now the use of self in a class method should make more sense. We’re essentially doing this: def Album.all().

When should we use class methods instead of instance methods? Sometimes it’s obvious; if a method needs to deal with multiple (or all) instances of a class, it should be a class method. However, this may not always be cut and dry, at least at first.

So, here’s a good rule of thumb: if both class methods and instance methods are feasible solutions to a problem, it's generally better to go with an instance method. It's a best practice to encapsulate our code as much as possible, exposing methods only where needed. Since class methods are available on the entire class, they are more readily available (and less encapsulated) than instance methods.

For our current use cases, it will be obvious when we’ll need class methods, but make sure to use the above rule of thumb when needed.

Now it's time to actually write some class methods. In order to do so, we'll use class variables, which we'll discuss in the next lesson.

Class methods are called on the class itself, not an instance of an object. We create a class method by appending the method name to self. Here's an example:

 class Album

   def self.all()
   end
 end

This method can be called in our application like this:

Album.all()

Lesson 8 of 37
Last updated August 7, 2022