Read more

Don't forget: Automatically remove join records on has_many :through associations

Thomas Klemm
April 17, 2015Software engineer

Bad

# Given the following models

class Image < ActiveRecord::Base
  has_many :album_images
  has_many :albums, through: :album_images
end

class Album < ActiveRecord::Base
  has_many :album_images
  has_many :images, through: :album_images
end

# Join model
class AlbumImage < ActiveRecord::Base
  belongs_to :album
  belongs_to :image
end

Destroying a record in this setup will only remove the record itself, and leave orphaned join records behind.

image = Image.last
image.destroy # removes only the `image` record,
              # but none of the associated `album_image` join records

Good

Illustration book lover

Growing Rails Applications in Practice

Check out our e-book. Learn to structure large Ruby on Rails codebases with the tools you already know and love.

  • Introduce design conventions for controllers and user-facing models
  • Create a system for growth
  • Build applications to last
Read more Show archive.org snapshot

By adding the :dependent => :destroy option to the has_many :through associations, the join records will be removed when an image or an album is destroyed.

class Image < ActiveRecord::Base
  has_many :album_images
  has_many :albums, through: :album_images, dependent: :destroy
end

class Album < ActiveRecord::Base
  has_many :album_images
  has_many :images, through: :album_images, dependent: :destroy
end

Note: the associated record with through (the albums in the example) will never be deleted by specifying dependent: :destroy, only the join records. Thus the following example will have the same effect as the above and is more explicit:

class Image < ActiveRecord::Base
  has_many :album_images, dependent: :destroy
  has_many :albums, through: :album_images
end
Posted by Thomas Klemm to makandra dev (2015-04-17 14:18)