I'd like to run a rake task (apn:notifications:deliver from the apn_on_rails gem) from a delayed_job. In other words, I'd like enqueue a delayed job which will call the apn:notifications:deliver rake task.
I found this code http://pastie.org/157390 from http://geminstallthat.wordpress.com/2008/02/25/run-rake-tasks-with-delayedjob-dj/.
I added this code as DelayedRake.rb to my lib directory:
require 'rake'
require 'fileutils'
class DelayedRake
def initialize(task, options = {})
@task = task
@options = options
end
##
# Called by Delayed::Job.
def perform
FileUtils.cd RAILS_ROOT
@rake = Rake::Application.new
Rake.application = @rake
### Load all the Rake Tasks.
Dir[ "./lib/tasks/**/*.rake" ].each { |ext| load ext }
@options.stringify_keys!.each do |key, value|
ENV[key] = value
end
begin
@rake[@task].invoke
rescue => e
RAILS_DEFAULT_LOGGER.error "[ERROR]: task \"#{@task}\" failed. #{e}"
end
end
end
Everything runs fine until the delayed_job runs and it complains:
[ERROR]: task "apn:notifications:deliver" failed. Don't know how to build task 'apn:notifications:deliver'
How do I let it know about apn_on_rails? I'd tried require 'apn_on_rails_tasks' at the top of DelayedRake which didn't do anything. I also tried changing the directory of rake tasks to ./lib/tasks/*.rake
I'm somewhat new to Ruby/Rails. This is running on 2.3.5 on heroku.
Go to Websites & Domains and click Ruby. After gems installation you can try to run a Rake task by clicking Run rake task. In the opened dialog, you can provide some parameters and click OK - this will be equivalent to running the rake utility with the specified parameters in the command line.
Whenever you are testing Rake tasks, you need to load the tasks from the Rails application itself. Note that in your tests you should change MyApplication to the name of your application. This line locates the task by it's name and returns a Rake::Task object. Then, we call invoke on it, which executes the task.
You can create these custom rake tasks with the bin/rails generate task command. If your need to interact with your application models, perform database queries and so on, your task should depend on the environment task, which will load your application code.
I believe it's easier if you call it as a separate process. See 5 ways to run commands from Ruby.
def perform
`rake -f #{Rails.root.join("Rakefile")} #{@task}`
end
If you want to capture any errors, you should capture STDERR
as shown in the article.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With