Class Methods in Ruby

December 6, 2014

Class methods are methods defined on a class object, as opposed to instances of the class. These methods are accessible through the class object, but not through the individual instances of that class. Let's examine a Books class which includes a class method for finding the book object with the most pages.

              class Books
                attr_reader :title
                attr_accessor :page_count

                def initialize(string)
                  @title = string
                end

                def Books.largest(*books)
                  books.max_by(&:page_count)
                end
              end

              book1 = Books.new("The Name of the Wind")
              book1.page_count = 1000

              book2 = Books.new("Bossypants")
              book2.page_count = 100

              book3 = Books.new("Dune")
              book3.page_count = 300

              largest = Books.largest(.book1, book2, book3)
              puts largest.title
              => "The Name of the Wind"
            

Notice that defining the class method includes the reference to the class object: Books.largest. The method takes a number of book objects and returns the book with the largest page count. We still use instance methods when we set the page count and access the title of the largest book.

The purpose of class methods is to fill the role of methods that cannot be performed on individual instances of the class. For example, the built-in new method is a class method, because until an instance has been created, we cannot send it a method call! So new must be called on the class to first create the instance. In the Books example above, it would not make sense to ask an individual book instance to find the largest book out of all of them. It makes much more sense to ask the entire class of Books to find the largest book object. Creating a class method is thus partly a design decision.

Let's extend our class to incorporate a method that will alphabetize our books by title and then return the first book. Because it makes more sense to ask the class to alphabetize all the books, as opposed to asking one book object to alphabetize all instances, we'll use another class method.

              class Books
                attr_reader :title
                attr_accessor :page_count

                def initialize(string)
                  @title = string
                end

                def Books.largest(*books)
                  books.max_by(&:page_count)
                end

                def Books.alpha_first(*books)
                  alpha_array = books.sort_by(&:title)
                  alpha_array[0]
                end

              end

              book1 = Books.new("The Name of the Wind")

              book2 = Books.new("Bossypants")

              book3 = Books.new("Dune")

              first_book = Books.alpha_first(book1, book2, book3)
              puts first_book.title
              => "Bossypants"
            

Notice that the class method Books.alpha_first takes an array of books and returns the first element in a sorted array of book objects that is alphabetized by title. As such, we call the instance method title on the book object in order to get it to return just its title.

In conclusion, class methods are methods called on the class object. They represent methods that are not called on instances of a class, but on the class itself, for design and practical purposes.