ruby-on-railspostgresqlforeign-keysrails-migrations

How to write associations for a model with two foreign keys for the same relationship?


I've been coming back to a problem I haven't solved on my own. I've got a shipments table with two columns for addresses, namely to_address_id and from_address_id.

After looking at a related question (Same Model for Two belongs_to Associations migration), I am still confused. Here is my work so far. I haven't run the migration. I'm trying to resolve this in my mind before getting worked up about it and waste an hour or two. I really thank you for your help.

class AddAddressFromAndAddressToToAddress < ActiveRecord::Migration[6.0]
  def change
    add_reference :address, :address_from, null: false
    add_reference :address, :address_to, null: false
    add_foreign_key :address, :shipments, column: :to_address_id
    add_foreign_key :address, :shipments, column: :from_address_id
  end
en

Solution

  • If i understand correctly you want add origin and destiny address to shipping, correctly?

    In this case:

    If you want create a migration to create a relationship

    class AddOriginAndDestinyAddressToShipment < ActiveRecord::Migration[6.0]
      def change
        add_reference :shipments, :from_address, foreign_key: { to_table: :addresses }
        add_reference :shipments, :to_address, foreign_key: { to_table: :addresses }
      end
    end
    
    

    If you want create a model with a relationship

    class CreateShipments < ActiveRecord::Migration[6.0]
      def change
        create_table :shipments do |t|
          t.datetime :deadline
          t.references :from_address, null: false, foreign_key: { to_table: :addresses }
          t.references :to_address, null: false, foreign_key: { to_table: :addresses }
          t.timestamps
        end
      end
    end
    

    And model Shipment must be something like this

    class Shipment < ApplicationRecord
      belongs_to :to_address, class_name: 'Address'
      belongs_to :from_address, class_name: 'Address'
    end