2011-06-10 3 views
0

Je suis coincé sur un problème simple ici. Je construis une application qui gère une base de données de coupons, dont chacun a une date d'expiration. J'essaye de construire une tâche de rake qui supprimera les coupons expirés. Le code correspondant de la rakefile ressemble à ceci:Détruire un objet Rails 3 dans Rake?

desc "Deletes expired offers from the database." 
task :purge_expired => :environment do 
    today = Date.today.to_s    
    Offer.where('expires_on < ?', today).destroy 
end 

qui échoue cependant avec le message d'erreur suivant:

rake aborted! 
wrong number of arguments (0 for 1) 

Je ne suis pas sûr de savoir pourquoi. Quels arguments seraient nécessaires?

A titre d'expérience, je trouve que cela a bien fonctionné:

desc "Deletes expired offers from the database." 
task :purge_expired => :environment do 
    today = Date.today.to_s    
    puts Offer.where('expires_on < ?', today).count 
end 

qui a renvoyé le bon nombre de dossiers, donc je suppose que je suis rassembler avec succès les bons objets.

FWIW, j'ai essayé cela aussi, et n'a pas eu de chance:

desc "Deletes expired offers from the database." 
task :purge_expired => :environment do 
    today = Date.today.to_s 
    @offers = Offer.where('expires_on < ?', today) 
    @offers.destroy 
end 

Je suis un peu d'idées. Qu'est-ce que je fais mal ici?

Merci beaucoup pour votre aide. Je suis sûr que je n'aurais pas de travail s'il n'y avait pas Stack Overflow!

Répondre

1

Vous êtes proche. Vous avez juste besoin d'utiliser la méthode #destroy_all au lieu de #destroy. Ce dernier nécessite un argument id.

today = Date.today.to_s    
Offer.where('expires_on < ?', today).destroy_all 
+0

A travaillé comme un champion, @Rob Davis. Merci! –

1

Tout d'abord, pour aider à déboguer les choses de rake, invoquez-le avec l'option --trace. Votre problème ici n'est pas spécifique au rake.

Le Offer.where('expires_on < ?', today) va retourner une collection, et pas une seule instance de Offer et il n'y a pas une méthode destroy disponible pour la collection. Vous pouvez parcourir chaque offre expirée et appeler le destroy. Quelque chose comme ceci:

@offers = Offer.where('expires_on < ?', today) 
@offers.each { |offer| offer.destroy } 
+0

L'itération fonctionne, mais ActiveRecord :: Relation définit également les méthodes #destroy_all et #delete_all. –

+0

Cela a beaucoup de sens, @Aaron Hinni. Merci de clarifier. Je suis encore nouveau à Rails, et honnêtement seulement une sorte de compréhension ténue de la relation entre les tableaux, les collections et Active Record. J'ai encore de l'apprentissage à faire! –