Lesson Monday

Sometimes, we want to have our objects take a particular action at some point in their lifecycle. For example, we might want to capitalize the names of albums. While we could technically create a validation for this, users will find it really annoying if they have to resubmit the form until every word is capitalized. Instead, we can use a callback so our Rails application takes care of it for us. Let's add a callback to titleize album names.

Here's a test:

spec/album_spec.rb
describe Album do
  it("titleizes the name of an album") do
    album = Album.create({name: "giant steps", genre: "jazz"})
    expect(album.name()).to(eq("Giant Steps"))
  end
end

It will fail as expected. Now let's write a callback to get the test passing:

models/album.rb
class Album < ApplicationRecord
  ...
  before_save(:titleize_album)

  private
    def titleize_album
      self.name = self.name.titleize
    end
end

We add a callback that states the method titleize_album will be called before_save. Callbacks are methods that get called at certain points of an object's life cycle, such as before it is saved or after it is deleted.

We make our titleize_album method private. Technically, this method would work fine even if it weren't private. However, we only want it to be called inside the Album class. The whole point of this method is that it should only be used as a callback. By default, methods are public and we don't want this method to be used elsewhere. It's a best practice to make methods private if we don't want them to be called outside of the class. Before we move on, note that Ruby is so flexible that it's always possible to create a workaround to call a private method from outside a class. The point of private methods isn't to provide strict enforcement. Instead, we can use private methods to communicate our intentions to other developers and better encapsulate our code.

Our actual callback method is simple because Rails provides a titleize method. This is not a Ruby method. It's an additional method that Rails provides to make our lives easier. However, this method is rudimentary and will capitalize all words in a phrase. A title_case method like the one we created in section 1 of Ruby would be better here. Feel free to customize this callback in this way to make it more accurate.

One thing that may seem a bit confusing: why is a before before_save callback being triggered by a test that calls the create method? before_save is actually a point in the object creation lifecycle. before_create is also part of the object creation lifecycle, but it actually happens after before_save. Read the documentation on the object lifecycle to learn more.

Check out the section on callbacks in the Rails Guide. Callbacks will be part of this section's independent project, but don't worry — only a basic understanding of callbacks and a simple method will be expected.

Lesson 18 of 34
Last updated August 7, 2022