From 1c89e9979ec9be6e09609e8c7c5336a00ebf3ff3 Mon Sep 17 00:00:00 2001 From: David Cook Date: Wed, 11 Feb 2026 17:15:33 +1100 Subject: [PATCH] CreateVariantLinks [migration] Tried using the rails generator, but as usual it was a waste of time becuase it doesn't handle unusual cases. I found more good guidance from that stackoverflow post: > why are you worrying about your indexes? Build your app! Something's not right in the model, see next commit. --- app/models/spree/variant.rb | 4 ++++ app/models/variant_link.rb | 6 ++++++ .../20260211055758_create_variant_links.rb | 19 +++++++++++++++++++ db/schema.rb | 12 +++++++++++- 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 app/models/variant_link.rb create mode 100644 db/migrate/20260211055758_create_variant_links.rb diff --git a/app/models/spree/variant.rb b/app/models/spree/variant.rb index d6eda45ca8..1245154860 100644 --- a/app/models/spree/variant.rb +++ b/app/models/spree/variant.rb @@ -72,6 +72,10 @@ module Spree has_many :semantic_links, as: :subject, dependent: :delete_all has_many :supplier_properties, through: :supplier, source: :properties + has_many :variant_links, dependent: :delete_all + has_many :source_variants, through: :variant_links + has_many :target_variants, through: :variant_links + localize_number :price, :weight validates_lengths_from_database diff --git a/app/models/variant_link.rb b/app/models/variant_link.rb new file mode 100644 index 0000000000..cedecb5c6d --- /dev/null +++ b/app/models/variant_link.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +class VariantLink < ApplicationRecord + belongs_to :source_variant, class_name: 'Spree::Variant', touch: true + belongs_to :target_variant, class_name: 'Spree::Variant', touch: true +end diff --git a/db/migrate/20260211055758_create_variant_links.rb b/db/migrate/20260211055758_create_variant_links.rb new file mode 100644 index 0000000000..6d84484511 --- /dev/null +++ b/db/migrate/20260211055758_create_variant_links.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class CreateVariantLinks < ActiveRecord::Migration[7.1] + def change + # Create a join table to join two variants. One is the source of the other. + # Primary key index ensures uniqueness and assists querying. target_variant_id is the most + # likely subject and so is first in the index. + # An additional index for source_variant is also included because it may be helpful + # (https://stackoverflow.com/questions/10790518/best-sql-indexes-for-join-table). + create_table :variant_links, primary_key: [:target_variant_id, :source_variant_id] do |t| + t.integer :source_variant_id, null: false, index: true + t.integer :target_variant_id, null: false + + t.timestamps + end + add_foreign_key :variant_links, :spree_variants, column: :source_variant_id + add_foreign_key :variant_links, :spree_variants, column: :target_variant_id + end +end diff --git a/db/schema.rb b/db/schema.rb index aaef15970f..72a13aa378 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -258,8 +258,8 @@ ActiveRecord::Schema[7.1].define(version: 2026_03_06_015040) do t.text "white_label_logo_link" t.boolean "hide_groups_tab", default: false t.string "external_billing_id", limit: 128 - t.boolean "enable_producers_to_edit_orders", default: false, null: false t.boolean "show_customer_contacts_to_suppliers", default: false, null: false + t.boolean "enable_producers_to_edit_orders", default: false, null: false t.index ["address_id"], name: "index_enterprises_on_address_id" t.index ["is_primary_producer", "sells"], name: "index_enterprises_on_is_primary_producer_and_sells" t.index ["name"], name: "index_enterprises_on_name", unique: true @@ -1113,6 +1113,14 @@ ActiveRecord::Schema[7.1].define(version: 2026_03_06_015040) do t.datetime "updated_at", precision: nil, null: false end + create_table "variant_links", primary_key: ["target_variant_id", "source_variant_id"], force: :cascade do |t| + t.integer "source_variant_id", null: false + t.integer "target_variant_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["source_variant_id"], name: "index_variant_links_on_source_variant_id" + end + create_table "variant_overrides", id: :serial, force: :cascade do |t| t.integer "variant_id", null: false t.integer "hub_id", null: false @@ -1278,6 +1286,8 @@ ActiveRecord::Schema[7.1].define(version: 2026_03_06_015040) do add_foreign_key "subscriptions", "spree_payment_methods", column: "payment_method_id", name: "subscriptions_payment_method_id_fk" add_foreign_key "subscriptions", "spree_shipping_methods", column: "shipping_method_id", name: "subscriptions_shipping_method_id_fk" add_foreign_key "tag_rules", "enterprises" + add_foreign_key "variant_links", "spree_variants", column: "source_variant_id" + add_foreign_key "variant_links", "spree_variants", column: "target_variant_id" add_foreign_key "variant_overrides", "enterprises", column: "hub_id", name: "variant_overrides_hub_id_fk" add_foreign_key "variant_overrides", "spree_variants", column: "variant_id", name: "variant_overrides_variant_id_fk" add_foreign_key "vouchers", "enterprises"