假设我有一个这样的表
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的记录
发布于 2019-01-16 04:27:54
同意moveson的观点,即最好的方法是在数据库中定义一个索引,以强制执行不同的记录或允许您添加uniqueness validator to the model。
另一种选择是截取ActiveRecord create方法调用以防止重复:
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'},
])https://stackoverflow.com/questions/54203169
复制相似问题