1

I'm pretty new to Rails and for the first time, I want to use Heroku Scheduler to run periodical tasks in my rails application. As advised in the Tutorial, I created the following rake tasks in /lib/tasks/scheduler.rake

 desc "This task is called by the Heroku scheduler add-on"
task :auto_results => :environment do
    puts "Updating results..."
    @cups = Cup.all
@cups.each do |cup|
    cup.fix_current_results
end
    puts "done."
end

task :update_game_dates => :environment do
    puts "Updating game dates..."
    @cups = Cup.all
@cups.each do |cup|
    cup.update_game_dates
end
puts "done."
end

The task run fine in my local environment, but after pushin to Heroku and running the task, each abort with the following error:

rake aborted!
undefined method `name' for nil:NilClass

To me it seems that Heroku somehow can't access the database and so doesn't revieve an object on which it can perform methods.

Ideas anyone?

marc78
  • 35
  • 4

1 Answers1

1

You could do the following:

Use a class method in your Cup model. You can then call it using the rails runner Cup.my_class_methodcommand, and schedule this in the Heroku scheduler.

# app/models/cup.rb
class Cup < ActiveRecord::Base
  # Your existing code

  ##
  #  Class Methods
  #  that can be run by 'rails runner Cup.my_class_method'
  #  with the Heroku scheduler
  def self.auto_results
    find_each {|cup| cup.fix_current_results}
  end

  def self.update_game_dates
    find_each {|cup| cup.update_game_dates}
  end
end

Then schedule rails runner Cup.auto_resultsand rails runner Cup.update_game_dateswith the Heroku scheduler.

I've optimizied your code a litte in the process, ask away if you have any questions.

Thomas Klemm
  • 10,678
  • 1
  • 51
  • 54
  • Thanks for the answer but this doesn't work either, same error. In development environment it works, but this did my solution already. Thanks for the code optimization! – marc78 Sep 24 '12 at 20:39
  • Hm. I can't see inside you codebase, but could it be that you have some code like `cup.name` in one of your `fix_current_results` or `update_game_dates` methods where there should be `self.name` or even shorter `name`. You could edit your post and add these methods there, then I could have a look. – Thomas Klemm Sep 24 '12 at 21:49
  • I don't have my code in front of me right now, but I will try that out later. There are definately things like `cup.name` in it, so this might be a good hint. Why doesn' these methods work without `self.` in production? – marc78 Sep 25 '12 at 06:23
  • It's a question of the current scope your command is running in. `Cup.do_something` are class methods called on the Cup Model and they are defined with `def self.do_something; end`. Everthing in there has the Cup model as the current scope, so `find_each` as I write it above means actually `Cup.find_each`. Meanwhile running `@cup.do_this` on an instance of a the cup model are methods to be called upon instances of this class and they are defined with `def do_this; end`. In there the current scope is the @cup object, which you can read and manipulate by calling `self.name` or `self[:name]`. – Thomas Klemm Sep 25 '12 at 07:02
  • `self` can be omitted when reading variables and executing methods on this instance, so for reading the name you could write `name (or again: self.name, self[:name]) while for writing you have to use `self.name = ... or self[:name] = ...`. `name = ...` would create a local variable called name. I haven't found a good link right now, but here is a question similar to this yours: http://stackoverflow.com/questions/10805136/when-to-use-self-in-model – Thomas Klemm Sep 25 '12 at 07:14
  • Thomas, thanks for the explanation. I read about the difference between class and instance methods once but obviously didn't really get it. Still seems odd to me, that calling the methods locally is working, but in production it won't. I'll try it out later and will post if your suggestions are working. Thank you again for your effort! – marc78 Sep 25 '12 at 08:47