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

时间:2020-07-04 21:38:05

标签: ruby-on-rails data-migration ruby-on-rails-6 rails-migrations

我有一个现有的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

我想知道的是如何编写该迁移?表中已经有数据,因此我需要保留设置了保留ID的现有费用并保留链接。

1 个答案:

答案 0 :(得分:1)

请注意此处,并确保在出现错误时可以还原,以免丢失数据!

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

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

哦,一旦您确定一切正常,就可以使用其他迁移操作删除费用表中的Reservation_id列。这就是您可能会破坏数据的问题的关键点,因此请确保正确填充了联接表。

您实际上也不再需要连接模型,这只是填充连接表的一种便捷方法。因此,您可以删除charges_reservation.rb模型。

相关问题