假设我有一张这样的桌子
id user_id value
1 1 A
2 1 A
3 1 A
4 1 A
5 1 A
6 1 A
7 2 B
8 2 B
9 3 C
如您所见,该表中有很多重复项。对于每个重复项,我希望能够删除其中一个重复项,以便仍然为每个重复项记录保留一条记录。例如,对于具有user_id = 1
和value = A
的重复记录,我希望能够删除除其中之一以外的所有记录,以便我仍然剩下一个具有user_id = 1
值的记录。和value = A
答案 0 :(得分:0)
同意moveson的观点,最好的方法是在数据库中定义索引以强制执行不同的记录或允许您添加uniqueness validator to the model。
另一种选择是拦截ActiveRecord创建方法调用以防止重复:
class Example < ApplicationRecord
def self.create( attributes = nil, &block )
attributes.each {|attr| self.create(attr, &block) } if attributes.is_a? Array
return if find_by attributes
super attributes, &block
end
end
这里的基本思想是,如果您已经在数据库中看到具有相同属性值的记录,则中止...但是然后让ActiveRecord通过用super调用它来继续进行所有繁重的工作。
如果由于某种原因您无法对数据库进行控制以防止输入重复项,则可以尝试创建类方法以定期从系统中清除重复项的方法。
下面是一个方法示例,该方法将遍历整个记录集并使用哈希值来跟踪它是否曾经查看过这些值,如果是,则将其删除:
class Example < ApplicationRecord
def self.dedup
distinct = {}
all.each do |row|
if distinct[row.user_id] && distinct[row.user_id] == row.value
row.delete
else
distinct[row.user_id] = row.value
end
end
end
end
然后可以这样称呼它:Example.dedup
每当您希望清除重复的记录时。
对于那些希望在家中跟随的人,您可以使用以下迁移:
rails g model example user_id:integer value:string
和种子文件:
examples = Example.create([
{user_id: 1, value: 'A'},
{user_id: 1, value: 'A'},
{user_id: 1, value: 'A'},
{user_id: 1, value: 'A'},
{user_id: 1, value: 'A'},
{user_id: 1, value: 'A'},
{user_id: 1, value: 'A'},
{user_id: 2, value: 'B'},
{user_id: 2, value: 'B'},
{user_id: 3, value: 'C'},
])