2010-10-16 17 views

Respuesta

25

Cualquiera de estos métodos lo haría:

# 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

En Rails 4.2.0 debe enviar el mensaje correcto al objeto AR: 'Foo.all.order ('created_at DESC'). Limit (n)' – borjagvo

+0

Tenga en cuenta que esto funcionará en una [ActiveRecord :: Relation] (http: //apidock.com/rails/ActiveRecord/Relation/destroy_all) porque acepta 'condiciones'. NO funcionará en ActiveRecord :: CollectionProxy porque el método 'destroy_all' simplemente ejecuta' @ association.destroy_all' sin argumentos. (https://github.com/rails/rails/blob/58772397e9b790e80bcd4d8e51937dc82ecb719e/activerecord/lib/active_record/associations/collection_proxy.rb#L504-L506) Intentar utilizar argumentos en 'destroy_all' para un CollectionProxy generará un' ArgumentError' excepción. – anothermh

4

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

Esto destruirá todas las personas que cumplan con la condición. Así que todo lo que necesita es invertidas y condiciones destroy_all

+1

trabajado para mí, y si usted no está preocupado por sus callbacks del modelo en ejecución y asociaciones, puede llamar 'delete_all' vez de 'destroy_all' para hacer esto en un solo estado SQL DELETE para guardar instancias de un objeto modelo para cada registro. –

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

respuestas anteriores utilizan find o last requieren la creación de ActiveModel, que tienen tiempo de cálculo adicional.

Creo que usar pluck es mejor, ya que solo crea una matriz de identificadores.

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

que tienen dos métodos de hacer esto, suponiendo que n = 5:

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

Esta clasifica los registros, con el último primero, y destruye todo más allá de los registros de 5to. O

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

Esto encuentra el sexto última ID de registro y elimina todos los registros con id = < sexto última ID de registro.

Además, es posible que desee ver este SO question.

+0

Buena idea usando '.offset'. ¡Gracias! – dgilperez

+0

¡La solución más Rails'y aquí, gracias! – Dan

0

[5 rieles/ActiveRecord :: Relation]

destroy_all ya no toma parámetros ... parámetros realidad, el ActiveRecord :: Relation nunca permitió que no creo ... De todos modos, sólo debe poner la condición antes, pero el uso de destroy_all después de la consulta, así:

Person.destroy_all("last_login < '2004-04-04'") 
Person.destroy_all(status: "inactive") 
Person.where(age: 0..18).destroy_all 
Cuestiones relacionadas