Rails 5 - 多个外键属于同一个表

Sve*_*ten 3 postgresql activerecord ruby-on-rails ruby-on-rails-5

我有一个属于 LoadingStation 模型的订单模型。并且 LoadingStation 将在 Order 表中使用两次,所以它看起来像:

class CreateLoadingStations < ActiveRecord::Migration[5.0]
  def change
    create_table :loading_stations do |t|
      t.integer :type
      t.string :comp_name1
      t.string :street
      t.string :street_num
      t.string :zip_code
      t.string :city

      t.timestamps
    end
  end
  end



 class CreateOrders < ActiveRecord::Migration[5.0]
      def change
         create_table :orders do |t|
          t.string :status
          t.belongs_to :loading_station, class_name: "LoadingStation", index: true, foreign_key: "loading_station_id"
          t.belongs_to :unloading_station, class_name: "LoadingStation", index: true, foreign_key: "unloading_station_id"

          t.timestamps
        end
      end
    end
Run Code Online (Sandbox Code Playgroud)

当我运行Rails db:migrate时,出现以下错误: ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: 关系“unloading_stations”不存在

嗯嗯,似乎没有正确检测到 class_name。两个语句中的 class_name 应该相同,对吗?

让我们检查一下装载站的型号:

 class LoadingStation < ApplicationRecord
end
Run Code Online (Sandbox Code Playgroud)

好的,我更改 CreateOrders 迁移:

 t.belongs_to :loading_station, class_name: "LoadingStation", index: true, foreign_key: "unloading_station_id"
Run Code Online (Sandbox Code Playgroud)

现在,当我运行 Rails db:migrate 时,出现此错误: ActiveRecord::StatementInvalid: PG::DuplicateObject: ERROR: 关系“orders”的约束“fk_rails_5294e269cc”已经存在

好的,我知道数据库中的外键似乎是相同的,并且数据库拒绝了迁移任务。

但是,当数据库检测到两个相同的外键名称时,当我定义不同的外键名称时,foreign_key: 选项的意义是什么?

附录:

这是我的订单模型:

class Order < ApplicationRecord
end
Run Code Online (Sandbox Code Playgroud)

最后一个问题

最后 - 在错误消息中 - 我希望有两个外键指向同一个表。

Tob*_*obi 6

我将只关注允许您两次引用装载站表的代码

在 Rails 5.1 或更高版本中,您可以这样做:

移民

class createOrders < ActiveRecord::Migration
   def change
    create_table(:orders) do |t|
        t.references :loading_station, foreign_key: true
        t.references :unloading_station, foreign_key: { to_table: 'loading_stations' }
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

这将创建字段loading_station_id,并对表unloading_station_id进行数据库级引用。loading_stations

楷模

class Order < ActiveRecord::Base
  belongs_to :loading_station
  belongs_to :unloading_station, class_name: "LoadingStation"
end

class LoadingStation < ActiveRecord::Base
  has_many :load_orders, class_name: "Order", foreign_key: "loading_station_id"
  has_many :unload_orders, class_name: "Order", foreign_key: "unloading_station_id"
end
Run Code Online (Sandbox Code Playgroud)