2010-10-16 74 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 
相關問題