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 UI/UX Design

UI/UX Design by makandra brand

We make sure that your target audience has the best possible experience with your digital product. You get:

  • Design tailored to your audience
  • Proven processes customized to your needs
  • An expert team of experienced designers
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)