1

I'm stuck on a simple issue here. I'm building an application that manages a database of coupons, each of which has an expiration date. I'm trying to build a rake task that will delete the expired coupons. The relevant code from the rakefile looks like this:

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

That however fails with the following error message:

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

I'm just not sure why. What arguments would be needed?

As an experiment, I found that this worked fine:

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

That returned the right number of records, so I assume I'm successfully gathering up the right objects.

FWIW, I tried this too, and had no luck:

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

So I'm kind of out of ideas. What am I doing wrong here?

Thanks so much for your help. I'm pretty sure I wouldn't have a job if it weren't for Stack Overflow!

Chris Allen Lane
  • 6,334
  • 5
  • 25
  • 31

2 Answers2

1

First off, to help debug things from rake, invoke it with the --trace option. Your issue here isn't rake specific though.

The Offer.where('expires_on < ?', today) is going to return a collection, and not a single instance of Offer and there isn't a destroy method available for the collection.

You can iterate over each expired offer and call destroy. Something like this:

@offers = Offer.where('expires_on < ?', today)
@offers.each { |offer| offer.destroy }
Aaron Hinni
  • 14,578
  • 6
  • 39
  • 39
  • Iterating works, but ActiveRecord::Relation also defines #destroy_all and #delete_all methods. – Rob Davis Jun 10 '11 at 20:30
  • That makes a lot of sense, @Aaron Hinni. Thanks for clarifying. I'm still new to Rails, and honestly only have kind of a tenuous understanding of the relationship of arrays, collections, and Active Record. I've still got some learning to do! – Chris Allen Lane Jun 10 '11 at 20:33
1

You're close. You just need to use the #destroy_all method instead of #destroy. The latter requires an id argument.

today = Date.today.to_s            
Offer.where('expires_on < ?', today).destroy_all
Rob Davis
  • 15,597
  • 5
  • 45
  • 49