Let’s say we have “products” and we want to prepare “kits” of those products. Kits are nothing but the group of the products.
We can use many-to-many relationship here because products can be in many kits, and kits can be associated with many products.
Also, since the kits are just grouping the products, we can use self-joins. There are multiple ways we can implement self-joins.
Using has_and_belongs_to_many
You can read more about has_and_belongs_to_many on Rails docs.
Migration
class CreateJoinTableProductKits < ActiveRecord::Migration[6.0] def change create_table :product_kits, id: false do |t| t.references :product, null: false, foreign_key: true, index: false t.references :kit, null: false, foreign_key: { to_table: :products }, index: false t.index [:product_id, :kit_id], unique: true end end end Model
class Product < ApplicationRecord has_and_belongs_to_many :kits, join_table: :product_kits, class_name: 'Product', association_foreign_key: 'kit_id' end Using has_many through
This approach is better because later on in your project you can add more fields and validations in ProductKit model.As you know, our projects are always dynamic and most of the time(all the time) we end up modifying the flow. So, it isbetter to be prepared and use has_many :through from the beginning.
More on, has_many :through on Rails docs.
Migration
class CreateJoinTableProductKits < ActiveRecord::Migration[6.0] def change create_table :product_kits do |t| t.references :product, null: false, foreign_key: true, index: false t.references :kit, null: false, foreign_key: { to_table: :products }, index: false t.index [:product_id, :kit_id], unique: true t.timestamps end end end Model app/models/product.rb
class Product < ApplicationRecord has_many :product_kits, dependent: :destroy has_many :kits, through: :product_kits end Model app/models/product_kit.rb
class ProductKit < ApplicationRecord belongs_to :product belongs_to :kit, class_name: 'Product' end
Top comments (2)
Wow, really helpful.
Thanks