2

Say I have a table products and want to maintain similar_products for each product.

Eyeslandic
  • 14,553
  • 13
  • 41
  • 54
druk
  • 553
  • 6
  • 16

3 Answers3

4

This is the migration for the self-referential table.

create_table :similar_products, id: false do |t|
      t.references :product, foreign_key: true, null: false
      t.references :similar_product, foreign_key: { to_table: :similar_products }
    end
druk
  • 553
  • 6
  • 16
4
class SimilarProductRelation < ApplicationRecord
  belongs_to :product
  belongs_to :similar_product, class_name: "Product"
end

class Product < ApplicationRecord
  # self being the "origin"
  has_many :similar_products_relations, source: :product_id, class_name: "SimilarProductRelation"
  has_many :similar_products, class_name: "Product", through: :similar_products_relations

  # self being the "destination"
  has_many :similar_products_relations_as, source: :similar_product_id, class_name: "SimilarProductRelation"
  has_many :similar_products_as, class_name: "Product", through: :similar_products_relations
end

# migration
create_table :similar_product_relations do |t|
  t.references :product, foreign_key: true, null: false, index: true
  t.references :similar_product, foreign_key: { to_table: :products }, null: false, index: true 
end

Index true or not depending on which direction you're going to make queries, and you can only keep one direction in the association, in the Product class, if you're only going to use one.

rogercampos
  • 1,676
  • 1
  • 10
  • 8
2

You can try the following ways :

class Product < ActiveRecord::Base
   belongs_to :product, :class_name => 'Product'
   has_many :similar_products, :class_name => 'Product', :foreign_key => 'parent_id'
end

The migrations can be added as :

add_column :products, :parent_id, :integer, null: true, index: true
add_foreign_key :products, :products, column: :parent_id
army_coding
  • 154
  • 6