模型关联在生产环境中发生变化,特别是将模型转换为多态?

时间:2010-05-12 15:42:21

标签: ruby-on-rails activerecord

我希望能够获得有关模型如何在已投入生产的应用中发挥重大变化的反馈。

在我的情况下,我有一个模型记录,有很多PhoneNumbers。

目前,这是一个典型的has_many belongs_to关联,其记录包含许多PhoneNumbers。

当然,我现在有一个添加临时用户生成记录的功能,这些记录也会有PhoneNumbers。

我只能将user_record_id添加到PhoneNumber模型中,但这不是更好的多态关联吗?

如果是这样,如果你改变一个模型关联的方式,我将如何在不破坏所有内容的情况下更新生产数据库? >。<

无论如何,只是在这样的情况下寻找最佳实践。

谢谢!

2 个答案:

答案 0 :(得分:1)

有两种方法可以帮助你解决这个问题。

一个是介绍一个处理电话号码集合的中间模型。这样,您的Record和UserRecord都可以属于此收集模型,并且可以从那里关联电话号码和其他联系信息。你最终会得到一个如下所示的关系:

class Record < ActiveRecord::Base
  belongs_to :address_book
  delegate :phone_numbers, :to => :address_book
end

class UserRecord < ActiveRecord::Base
  belongs_to :address_book
  delegate :phone_numbers, :to => :address_book
end

class AddressBook < ActiveRecord::Base
  has_many :phone_numbers
end

这种重新编译可以通过迁移和一些SQL来完成,以根据记录中已有的内容填充address_books表中的列。

另一种方法是使UserRecord成为STI派生类型的Record,这样在定义关联时就不需要处理两个不同的表。

class Record < ActiveRecord::Base
  has_many :phone_numbers
end

class UserRecord < Record
end

通常,您需要做的就是在模式中引入“类型”字符串列,然后您可以使用STI。如果UserRecord条目在一段时间后应该过期,则可以使用以下内容轻松删除它们:

UserRecord.destroy_all([ 'created_at<=?', 7.days.ago ])

使用STI方法时,您必须小心选择范围,以便根据您打算执行的操作仅检索永久或临时记录。由于UserRecord是从Record派生的,因此您会发现它们在默认加载期间也会被加载,例如:

@records = Record.find(:all)

如果这会导致问题,您可以始终将Record用作抽象基类,并创建派生的PermanentRecord类来解决此问题:

class PermanentRecord < Record
end

使用以下内容进行迁移时更新:

add_column :records, :type, :string
execute "UPDATE records SET type='PermanentRecord'"

然后你可以使用PermanentRecord代替Record来代替所有现有代码,它不应该无意中检索UserRecord条目。

答案 1 :(得分:-1)

维护页面是您的答案。

  1. 生成迁移,更新表结构并更新现有数据。如果您反对迁移中的数据更新 - 请使用rake任务。
  2. 禁用网络访问(创建维护页面)
  3. 部署新代码
  4. 运行待定迁移
  5. 更新数据
  6. 启用Web访问(删除维护页面)。