如何组合重复的rails对象并更新所有引用

时间:2013-01-17 12:12:54

标签: ruby-on-rails duplicates

我正在开发一个Rails应用程序(Ruby 1.9.2 / Rails 3.0.3),可以随时跟踪不同团队中的人员及其成员资格。我无法想出一种可扩展的方法来组合重复的Person对象。通过'combine',我的意思是删除除了一个重复的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

Crew.rb

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

Roster.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行动。

因此,在createupdate操作中,我想实现对重复Person对象的检查,删除重复项,然后更新所有crew和{{1}引用指向剩余的roster

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

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

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

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

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

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

最后,为确保您的代码正常工作,您可能希望在Person模型上添加一个验证,以防止现有代码重复。类似的东西:

validates :iqcs_num, :uniqueness => true, :allow_nil => true