我正在开发一个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
的真正唯一字段(可以将其视为社会安全号码),可以选择将其存储在create
或update
行动。
因此,在create
和update
操作中,我想实现对重复Person对象的检查,删除重复项,然后更新所有crew
和{{1}引用指向剩余的roster
。
在每个型号上使用Person
是否安全?这似乎是一种蛮力,特别是因为我将来可能会添加更多依赖于Person的模型,我不想记得维护find_duplicate函数。
感谢您的帮助!
答案 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