In this lesson, we'll set up a one-to-many relationship between
songs. We'll save our many-to-many relationship between
artists for a later lesson.
We've already created our
albums table. Let's set up our
songs table now:
$ rails g migration create_songs
Here's how our new migration should look. Note how Active Record automatically knows that we want to create a
songs table because we named our migration
class CreateSongs < ActiveRecord::Migration[5.2] def change create_table :songs do |t| t.column(:name, :string) t.column(:lyrics, :string) t.column(:album_id, :integer) t.timestamps end end end
This looks similar to our
albums table. The difference is that we add an
album_id so we can make a one-to-many association between
Make sure to save the file and run the migration.
Let's make one more migration before we continue. This one will officially make
album_id a foreign key:
rails g migration add_foreign_key_for_songs
Here's the migration:
class AddForeignKeyForSongs < ActiveRecord::Migration[5.2] def change add_foreign_key :songs, :albums end end
Adding a foreign key is optional. Active Record offers this option so we can guarantee "referential integrity".
Our databases are now set up for an association between
albums. The next step is to add this relationship to our classes.
Let's start by creating a model with a
Song class. We'll include the necessary code for the relationship as well:
class Song < ApplicationRecord belongs_to :album end
When a class has a "belongs to" relationship with another class, we use Active Record's
belongs_to, which takes another class as an argument. Note that the class is indicated with a symbol:
Now let's update our
class Album < ApplicationRecord has_many :songs end
Active Record is just using plain English. An instance of an
has_many(:songs). Note the pluralized syntax of
:songs here. Just like that, we've set up a one-to-many relationship between
Note that this new relationship will automatically create several new methods, including
One more thing: what if we want to make sure that an instance of
Song is destroyed when the
Album instance it belongs to is destroyed? This is easy, too:
class Album < ApplicationRecord has_many :songs, dependent: :destroy end
We simply add
dependent: :destroy to our code.
We should still test this relationship, though. Wouldn't it be nice if we had a really easy way to test this kind of thing? Fortunately, there's shoulda-matchers, a gem that makes these tests much easier. We'll cover testing with shoulda-matchers soon.
Lesson 6 of 34
Last updated July 14, 2022