2010-10-16 29 views

Trả lời

25

Một trong những phương pháp này sẽ làm điều đó:

# 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

Trong Rails 4.2.0 bạn phải gửi thông điệp chính xác đến đối tượng AR: 'Foo.all.order ('created_at DESC'). Limit (n)' – borjagvo

+0

Lưu ý rằng điều này sẽ làm việc trên [ActiveRecord :: Relation] (http: //apidock.com/rails/ActiveRecord/Relation/destroy_all) vì nó chấp nhận 'điều kiện'. Nó sẽ không hoạt động trên ActiveRecord :: CollectionProxy vì phương thức 'destroy_all' chỉ chạy' @ association.destroy_all' mà không có đối số. (https://github.com/rails/rails/blob/58772397e9b790e80bcd4d8e51937dc82ecb719e/activerecord/lib/active_record/associations/collection_proxy.rb#L504-L506) Cố gắng sử dụng các đối số trong 'destroy_all' cho một CollectionProxy sẽ tăng một' ArgumentError' ngoại lệ. – anothermh

4

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

Điều này sẽ phá hủy tất cả những người đáp ứng điều kiện. Vì vậy, bạn chỉ cần có điều kiện ngược và destroy_all

+1

Làm việc đối với tôi, và nếu bạn không phải lo lắng về callbacks mô hình của bạn chạy và các hiệp hội, bạn có thể gọi 'delete_all' thay của 'destroy_all' để làm điều này trong một trạng thái DELETE SQL đơn để lưu instantiating một đối tượng mô hình cho mỗi bản ghi. –

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

câu trả lời trước sử dụng find hoặc last đòi hỏi sự sáng tạo của ActiveModel, mà mất thêm thời gian tính toán.

Tôi nghĩ sử dụng pluck là tốt hơn, vì nó chỉ tạo ra một mảng id.

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

Tôi có hai phương pháp để làm điều này, giả sử n = 5:

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

này phân loại hồ sơ với mới nhất đầu tiên, và phá hủy tất cả mọi thứ quá khứ kỷ lục thứ 5. Hoặc

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

Điều này tìm thấy id hồ sơ mới nhất thứ 6 và xóa tất cả các bản ghi với id < = id hồ sơ mới nhất thứ 6.

Ngoài ra, bạn có thể muốn xem SO này là SO question.

+0

Ý tưởng hay sử dụng '.offset'. Cảm ơn! – dgilperez

+0

Giải pháp Rails'y nhất tại đây, cảm ơn! – Dan

0

[Rails 5/ActiveRecord :: Relation]

destroy_all không còn mất các thông số ... thông số thực tế, các ActiveRecord :: Quan hệ không bao giờ cho phép tôi không nghĩ rằng ... Dù sao, bạn nên chỉ đặt điều kiện trước đó, nhưng sử dụng destroy_all sau truy vấn, như thế này:

Person.destroy_all("last_login < '2004-04-04'") 
Person.destroy_all(status: "inactive") 
Person.where(age: 0..18).destroy_all 
Các vấn đề liên quan