0

我正在开发一个 Rails 应用程序(Ruby 1.9.2 / Rails 3.0.3),它会随着时间的推移跟踪人员及其在不同团队中的成员身份。我无法想出一种可扩展的方式来组合重复的 Person 对象。通过“组合”,我的意思是删除除一个重复的 Person 对象之外的所有对象,并更新所有引用以指向该 Person 的剩余副本。这是一些代码:

楷模:

人物.rb

class Person < ActiveRecord::Base
  has_many :rostered_people, :dependent => :destroy
  has_many :rosters, :through => :rostered_people
  has_many :crews, :through => :rosters

    def crew(year = Time.now.year)
      all_rosters = RosteredPerson.find_all_by_person_id(id).collect {|t| t.roster_id}
      r = Roster.find_by_id_and_year(all_rosters, year)
      r and r.crew
    end
end

船员.rb

class Crew < ActiveRecord::Base
  has_many :rosters
  has_many :people, :through => :rosters
end

名册.rb

class Roster < ActiveRecord::Base
  has_many :rostered_people, :dependent => :destroy
  has_many :people, :through => :rostered_people
  belongs_to :crew
end

RosteredPerson.rb

class RosteredPerson < ActiveRecord::Base
  belongs_to :roster
  belongs_to :person
end

Person可以仅使用名字和姓氏创建对象,但它们有一个真正唯一的字段,称为iqcs_num(将其视为社会安全号码),可以选择将其存储在createupdate操作中。

因此,在createandupdate操作中,我想实现对重复的 Person 对象的检查,删除重复的对象,然后更新所有的crewandroster引用以指向剩余的Person.

.update_all在每种型号上使用是否安全?这似乎是一种蛮力,特别是因为我将来可能会添加更多依赖于 Person 的模型,而且我不想记住维护 find_duplicate 函数。

谢谢您的帮助!

4

1 回答 1

0

处理此问题的“可扩展”方法是使重复数据删除过程成为应用程序正常功能的一部分 - 每当您保存记录时,请确保它不是重复的。您可以通过向Person 模型添加回调来做到这一点。也许是这样的:

before_save :check_for_duplicate

def check_for_duplicate
  if iqcs_num
    dup = Person.find_by_iqcs_num(self.iqcs_num)
    if dup && dup.id != self.id
      # move associated objects to existing record
      dup.crews = dup.crews + self.crews

      # update existing record
      dup.update_attributes(:name => self.name, :other_field => self.other_field)

      # delete this record
      self.destroy

      # return false, so that no other callbacks get triggered
      return false
    end
  end
end

您需要确保在 iqcs_num 列上为存储 Person 对象的表建立索引,以便随着记录数量的增长,此查找保持高效 - 毕竟每次更新 Person 记录时都会执行此查找.

我不知道您是否可以不让回调保持最新 - 完全有可能必须以不同方式移动不同类型的关联对象。另一方面,它只存在于一个地方,而且无论如何您都将在同一个地方添加关联 - 在模型中。

最后,为了确保您的代码正常工作,您可能需要在 Person 模型上添加一个验证,以防止重复存在。就像是:

validates :iqcs_num, :uniqueness => true, :allow_nil => true
于 2013-01-17T16:32:31.840 回答