2010-10-16 56 views

回答

25

这两种方法都将做到这一点:

# Fetch your latest N records 
newest_n_records = Foo.find(:all, :order => 'created_at DESC', :limit => n) 

# Then do: 
Foo.destroy_all(['id NOT IN (?)', newest_n_records.collect(&:id)]) 

# Or: 
Foo.destroy_all('created_at < ?', newest_n_records.last.created_at) 
+0

在Rails 4.2.0中,您必须向AR对象发送正确的消息:'Foo.all.order('created_at DESC')。limit(n)' – borjagvo 2016-02-17 12:15:25

+0

请注意,这可以在[ActiveRecord :: Relation] //apidock.com/rails/ActiveRecord/Relation/destroy_all),因为它接受'条件'。它不会在ActiveRecord :: CollectionProxy上工作,因为'destroy_all'方法只是在不带参数的情况下运行'@ association.destroy_all'。 (https://github.com/rails/rails/blob/58772397e9b790e80bcd4d8e51937dc82ecb719e/activerecord/lib/active_record/associations/collection_proxy.rb#L504-L506)尝试在'destroy_all'中为CollectionProxy使用参数将引发'ArgumentError'例外。 – anothermh 2016-05-17 00:09:30

4

Person.destroy_all("last_login < '2004-04-04'")

这将破坏谁符合条件的所有人员。因此,所有你需要的是反转的条件和destroy_all

+1

为我工作,如果你不担心运行模型回调和协会,你可以叫'delete_all'代替'destroy_all'在单个SQL DELETE状态下执行此操作以保存实例化每个记录的模型对象。 – 2013-08-06 15:43:52

6
Foo.destroy_all(['id NOT IN (?)', Foo.last(1000).collect(&:id)]) 
0

以前的答案使用findlast需要加载ActiveModel创造的,这需要额外的计算时间。我认为使用pluck更好,因为它只创建一个id数组。

ids = Foo.limit(n).order('id DESC').pluck(:id) 
Foo.where('id NOT IN (?)', ids).destroy_all 
13

我必须这样做,假设两种方法N = 5:

Foo.order('id desc').offset(5).destroy_all 

这与最新的第一对记录进行排序,并摧毁一切都会过去5日的记录。或

Foo.destroy_all(['id <= ?', Foo.order('id desc').limit(1).offset(5).first.id]) 

这个发现第六届最新记录ID和ID < = 6日最新记录ID将删除所有记录。

此外,你可能想看看这个SO question

+0

使用'.offset'的好主意。谢谢! – dgilperez 2015-05-19 14:02:36

+0

大多数Rails'y解决方案在这里,谢谢! – Dan 2016-06-14 19:21:03

0

[Rails的5 /的ActiveRecord ::关系]

destroy_all不再需要的参数......其实,ActiveRecord的::关系决不允许参数我不认为做...无论如何,你应该只把条件之前,但使用destroy_all 后的查询,例如:

Person.destroy_all("last_login < '2004-04-04'") 
Person.destroy_all(status: "inactive") 
Person.where(age: 0..18).destroy_all 
相关问题