This tutorial covers the basics of implementing a one-to-many relationship in Ruby on Rails. There are many options available to you when creating this relationship. You should be aware of these, and I will cover a few of the important ones. I will also show you some of the methods Rails gives you access to in the relationship.

Related: Ruby on Rails many-to-many Tutorial
Related: Ruby on Rails one-to-one Tutorial

In this example I will be creating a one-to-many relationship between Artists and Albums.

In Ruby on Rails a one-to-many relationship is defined by using has_many in the base, and belongs_to in the associated model.

Setup The Relationship

Database

# artists table
create_table :artists do |t|
  t.string :name
  t.timestamps
end
 
# albums table
create_table :albums do |t|
  t.string :genre
  t.string :name
  t.string :description
  t.integer :artist_id
  t.timestamps
end

Defining The Relationship In Your Model

# models/artist.rb
class Artist < ActiveRecord::Base
  has_many :albums
end
 
# models/album.rb
class Album < ActiveRecord::Base
  belongs_to :artist
end

Using The Relationship

The relationship is now setup! Easy yeah? Now you can use these useful methods in your controller and view.

#  Get all the the artists
@artists = Artist.find(:all)
 
# Find artist by name
@artist = Artist.find_by_name("Snoop Dog")
 
# Delete an album for the artist
@artist.albums.delete(params[:id])
 
# Delete all albums for the artist
@artist.albums.clear
 
#  Check if artist has no albums
if(@artist.albums.empty?)
  ...
end
 
# Create an album for the artist
@artist.albums.create("genre" => "Pop", "name" => "Rap 2008")
 
# Count the number of albums for an artist
@artist.albums.size
 
# Swap one artists albums with another artist
@artist1.albums = @artists2.albums

Customising The Relationship

There are many different options that can be used with the has_many method. These are very important and can also simplify a lot of your code.

For example: If you always want the albums in your artist object to be sorted by its name then you can use the following code:

# models/artist.rb
class Artist < ActiveRecord::Base
  has_many :albums, :order => 'name ASC'
end

More complex examples:

# Default model name is not Album, it is SpecialAlbum
has_many :albums, :class_name => 'SpecialAlbum'
 
# Using conditions to provide a list of pop albums for an artist
has_many :pop_albums, :conditions => ["genre = ?", "Pop"], :class_name => 'Album'
 
# The reference id column is different to the model name
has_many :albums, :foreign_key => "singer_id"
 
# Custom SQL
has_many :custom_albums, :class_name => "Album", :finder_sql =>
      'SELECT al.* ' +
      'FROM artists a, albums al ' +
      'WHERE al.artist_id = a.id AND al.genre = #{genre}'