Ben Downey
Ben Downey

Reputation: 2665

Rails app Rake task doesn't know how to build other Rake task

I'm trying to create a Rake task that invokes two other rake tasks. I've found people with related questions here and here, but it hasn't been very useful. This is what I've cobbled together so far. Any idea what I'm doing wrong?

task :cron => :environment do
  #if Time.now.hour % 2  == 0 
    Rake::Task["robots:update_robots"].reenable
    Rake::Task["robots:update_robots"].invoke
  #end
end

As you can see, it's a cron job that's meant for Heroku to do. But I've commented out what I don't need so I can test that it's working.

I keep getting this error:

Don't know how to build task 'robots:update_robots'

But I have no idea why.

UPDATE: So I it turns out I wasn't able to run the original task that was being called by my cron rake task. I had it running ok for a while, buy somewhere along the line, I deleted the "d" in "update". So this command Rake::Task["robots:upate_robots"].execute didn't because the robots rake task was "upate", not "update".

Tl;dr: typos.

Upvotes: 2

Views: 3657

Answers (1)

Joshua Cheek
Joshua Cheek

Reputation: 31726

In general, your solution should work:

require 'rake'

task :environment do
  puts 'task environment'
end

namespace :robots do
  task :update_robots do
    puts "task robots:update_robots"
  end
end

task cron: :environment do
  puts 'task cron'
  Rake::Task['robots:update_robots'].reenable
  Rake::Task['robots:update_robots'].invoke
end

Rake::Task['robots:update_robots'].invoke
Rake::Task[:cron].invoke

# >> robots:update_robots was invoked
# >> task robots:update_robots
# >> task environment
# >> task cron
# >> task robots:update_robots

My first thought is that you must have the rake task wrong (are you sure it's "robots:update_robots" ?)

It's unusual to me that you need to reenable it, this implies that what you want is not Rake, but just plain old Ruby. Move the contents of the update_robots task out to a method which you can then invoke directly instead of trying to treat tasks like methods (tasks are for handling dependencies, they only invoke once on purpose, and your need to bend them around that implies you're using the wrong tool for the job). Then, both your code and the robots:update_robots can just call the same method:

require 'rake'

def update_robots
  puts "method update_robots"
end

task :environment do
  puts 'task environment'
end

namespace :robots do
  task :update_robots do
    update_robots
    puts "task robots:update_robots"
  end
end

task cron: :environment do
  puts 'task cron'
  update_robots
end

Rake::Task['robots:update_robots'].invoke
Rake::Task[:cron].invoke

# >> method update_robots
# >> task robots:update_robots
# >> task environment
# >> task cron
# >> method update_robots

Upvotes: 3

Related Questions