如何将 rails 中的 has_many / belongs_to 关系迁移到 has_and_belongs_to_many?

How can I migrate a has_many / belongs_to relationship in rails to has_and_belongs_to_many?

我有一个现有的 rails 6 应用程序,其中有两个模型:

class Reservation << ApplicationRecord
# ...
  has_many :charges
# ...
end
class Charge << ApplicationRecord
# ...
  belongs_to :reservation
# ...
end

我想将其重构为:

class Reservation << ApplicationRecord
# ...
  has_and_belongs_to_many :charges
# ...
end
class Charge << ApplicationRecord
# ...
  has_and_belongs_to_many :reservation
# ...
end

我想知道的是那个migration怎么写? table 中已有数据,因此我需要保留已设置预订 ID 的现有费用并保留 link。

这里要小心,确保如果有错误你可以恢复,这样你就不会丢失你的数据!

首先,您需要通过迁移创建连接 table。您可以使用以下命令从命令行创建迁移:

rails g migration create_charges_reservations

这应该会在 db/migrate 中为您创建迁移模板,您将根据需要填充该模板,如下所示:

class CreateChargesReservations < ActiveRecord::Migration[6.0]
  def change
    create_table charges_reservations do |t|
      t.integer :charge_id
      t.integer :reservation_id
    end
  end
end

运行 从命令行迁移:

rails db:migrate

现在制作连接模型:

# app/models/charges_reservation.rb
class ChargesReservation < ApplicationRecord
  belongs_to :charge
  belongs_to :reservation
end

现在您必须迁移现有数据,因此从 rails 控制台:

Charge.all.each{|c| ChargesReservation.create(charge_id: c.id, reservation_id:c.reservation_id)}

最后将关联更改为您在问题中指出的 habtm 关联

# charge.rb
has_and_belongs_to_many :reservations

#reservation.rb
has_and_belongs_to_many :charges

哦,一旦您确定一切正常,您可以通过另一次迁移删除费用 table 中的 reservation_id 列。这是您可能会造成问题的地方 b/c 您正在破坏数据,因此请确保连接 table 已正确填充。

您实际上也不再需要连接模型,它只是一种填充连接的便捷方式 table。所以你可以删除charges_reservation.rb模型。