class ModifyCustomersTable < ActiveRecord::Migration[7.1] def up # First, remove the foreign key constraint from reservations remove_foreign_key :reservations, :customers if foreign_key_exists?(:reservations, :customers) # Create temporary columns without constraints add_column :customers, :first_name, :string unless column_exists?(:customers, :first_name) add_column :customers, :surname, :string unless column_exists?(:customers, :surname) add_column :customers, :original_phone, :string unless column_exists?(:customers, :original_phone) # Copy data execute <<-SQL UPDATE customers SET first_name = name, surname = '', original_phone = phone SQL # Now add the NOT NULL constraints change_column_null :customers, :surname, false change_column_null :customers, :original_phone, false # Remove old name column remove_column :customers, :name if column_exists?(:customers, :name) # Remove existing indexes remove_index :customers, name: :index_customers_composite_with_company, if_exists: true remove_index :customers, name: :index_customers_on_name_and_company_id, if_exists: true remove_index :customers, name: :index_customers_on_company_id, if_exists: true remove_index :customers, name: :index_customers_on_composite_key, if_exists: true remove_index :customers, name: :index_customers_on_composite_key_and_company, if_exists: true # Create new indexes add_index :customers, [:first_name, :surname, :original_phone], unique: true, name: 'index_customers_on_composite_key' add_index :customers, [:first_name, :surname, :original_phone, :company_id], unique: true, name: 'index_customers_on_composite_key_and_company' # Add a non-unique index on company_id for performance add_index :customers, :company_id, name: 'index_customers_on_company_id' # Add new columns to reservations add_column :reservations, :customer_first_name, :string add_column :reservations, :customer_surname, :string add_column :reservations, :customer_original_phone, :string # Update reservations data execute <<-SQL UPDATE reservations SET customer_first_name = (SELECT first_name FROM customers WHERE customers.id = reservations.customer_id), customer_surname = (SELECT surname FROM customers WHERE customers.id = reservations.customer_id), customer_original_phone = (SELECT original_phone FROM customers WHERE customers.id = reservations.customer_id) SQL # Add foreign key constraint add_foreign_key :reservations, :customers, primary_key: [:first_name, :surname, :original_phone], column: [:customer_first_name, :customer_surname, :customer_original_phone] # Remove old columns remove_column :customers, :id if column_exists?(:customers, :id) remove_column :reservations, :customer_id if column_exists?(:reservations, :customer_id) end def down # Add back the id columns add_column :customers, :id, :primary_key add_column :reservations, :customer_id, :integer # Remove the composite foreign key remove_foreign_key :reservations, :customers if foreign_key_exists?(:reservations, :customers) remove_column :reservations, :customer_first_name remove_column :reservations, :customer_surname remove_column :reservations, :customer_original_phone # Add back the original foreign key add_foreign_key :reservations, :customers # Drop composite indexes safely execute <<-SQL DROP INDEX IF EXISTS index_customers_on_composite_key; DROP INDEX IF EXISTS index_customers_on_composite_key_and_company; SQL # Restore the original columns add_column :customers, :name, :string execute "UPDATE customers SET name = first_name" remove_column :customers, :first_name remove_column :customers, :surname remove_column :customers, :original_phone end end