Heroku Scheduler rake task aborts - ruby-on-rails-3

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?

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.

Related

Invoking rake with whenever

I just started using Rails Whenever plugin. I have rake file cron. with task:
task :cron => :environment do
puts "Task invoked!"
end
And in schedule.rb I have this:
every 2.minutes do
rake "cron", enviroment => "development"
end
Once I start my app and specified interval passes, nothing happens? I am pretty new to Ruby and Rails so what am I doing wrong?
You'll need to write the schedule to your crontab. Run this command in your app:
bundle exec whenever --update-crontab myapp
When you run this command, whenever takes the Ruby syntax, translates it to cron syntax and adds it to your crontab.

Scheduling a Delay Job on Heroku with a Worker Dyno

I'm currently using Heroku's scheduler to run a script. However, the time that the script takes to run is going to increase from a few milliseconds to a few minutes. I'm looking at using the delayed_job gem to push this process off to a Worker Dyno. I want to continue to run this script once-a-day, just offload it to the worker. My current rake task is:
desc "This task updates some stuff for you."
task :update_some_stuff => :environment do
puts "Updating some stuff ..."
SomeClass.new.process
puts "... done."
end
Once the gem is installed, migration run, and worker dyno started, will the script just need to change to:
desc "This task updates some stuff for you."
task :update_some_stuff => :environment do
puts "Updating some stuff ..."
SomeClass.new.delay.process
puts "... done."
end
With this task still being a rake task scheduled by Heroku's Scheduler, is the only thing that needs to happen here the introduction of the delay method to put this in the Worker's queue?
Thanks in advance for any help.
Yes, DJ is a very simple gem, and you should be able to see this working correctly locally by adding a record to your delayed_jobs table in your database. With a worker running on Heroku everything should be fine.
Just make sure you have the following in your Procfile:
worker: bundle exec rake jobs:work
More information can be found here: https://devcenter.heroku.com/articles/delayed-job

How do I create a rake task for a Rails engine which is not exposed to the host application?

# lib/tasks/test.rake
task :hello do
puts 'hello'
end
$ rake app:hello
To run the task I need to prefix it with "app:" and it runs in the context of the dummy app. It is also exposed to the host application (i.e when used as a plugin in a parent Rails app) as rake hello.
I want to run a rake task which does not require a Rails environment and runs some command, but it is run from the engine root, not the dummy app root.
I know that's a bit late, but for others here searching for the correct answer, do the following :
Create your task :
# lib/tasks/your_engine_tasks.rake
desc "Explaining what the task does"
task :your_task do
# Task goes here
end
Then go to your engine ./Rakefile and add
load 'lib/tasks/your_engine_tasks.rake'
Here we go, now:
$ rake -T
gives you your task.
Hope I helped.
I want a better answer to this question however I did figure out that you can add tasks in the Rakefile for the engine (so ./Rakefile not in the spec/dummy application) like so:
task :my_task do
puts "hi!"
end
task :default => [:spec, :my_task]
I would prefer to have my task in another file but at least this provides a way to go forward. In my case, I want to run Konacha javascript tests in the dummy application so my Rakefile looks like this:
task :spec_javascript do
exec 'cd spec/dummy && rake konacha:run' # exec passes command return value up stack!
end
task :default => [:spec, :spec_javascript]

rails-3 cron job not working with rails runner

Recently I came across the following tutorial of running cron job without using any Gems
http://www.ameravant.com/posts/recurring-tasks-in-ruby-on-rails-using-runner-and-cron-jobs
I create one file in /app/delete_old_posts.rb
class DeleteOldPosts < ActiveRecord::Base
# This script deletes all posts that are over 5 minutes old
post_ids = Post.find(:all, :conditions => ["created_at < ?", 5.minutes.ago])
if post_ids.size > 0
Post.destroy(post_ids)
puts "#{post_ids.size} posts have been deleted!"
end
Then create cron job by giving crontab -e command and in console of cronjob I wrote
*/2 * * * * /usr/bin/env ruby /home/abc/xyz/urjit.rajgor/workspace/thewall/rails/runner/home/XYZ/ABC/urjit.rajgor/workspace/thewall/app/delete_old_posts.rb
cron job run after every two minutes but it did not work
Please help me.
Thanks
Try using the "whenever" gem.
Allows you to define your cronjobs in ruby being able to specify rails runner, rake, or other custom wrappers and it handles writing the crontab for you. Makes life much simpler.
Just add: gem 'whenever', :require => falseto your gemfile
https://github.com/javan/whenever
http://railscasts.com/episodes/164-cron-in-ruby

Automatically run gem tasks in test environment

I have a Rails 3 gem which has some rake tasks that should only be run in the test environment. Running in other environments doesn't really make sense.
My problem is Rake loads the Rails system in order to find my tasks in my gem. So by the time it gets to my tasks Rails is already loaded in the "development" environment (or whatever environment the user specified). This means in order to run my rake tasks properly the user must do:
RAILS_ENV=test rake mytask
Since my task only make sense in the "test" environment this is annoying as I would much rather the user be able to just type:
rake mytask
This is similar to how test:units and test:functionals automatically assume the test environment and the user doesn't need to specify RAILS_ENV=test at the command line. So the question is how do I modify my test so that Rails switches to the test environment?
My current workaround is:
Rails.env = 'test'
ActionMailer::Base.delivery_method = :test
require Rails.root.join('test/test_helper')
This seems to somewhat work but it is still logging to log/development.log and I think it is still actually running the "development" config. Anybody have any ideas? Looking at how the test tasks are defined in Rails itself doesn't reveal how to do it that I can see.
https://github.com/rails/rails/blob/master/railties/lib/rails/test_unit/testing.rake
UPDATE: I've updated my code after taking inputs from Eric's implementation at https://github.com/eric1234/test_inline/commit/fe3da7efa3a2cdb7824c23cfa41697b0ceb9e8e2.
For original code see - https://stackoverflow.com/posts/4600524/revisions
desc "Do something in Test environment"
task :example => :environment do
if not Rails.env.test?
Dir.chdir(Rails.root) do
system "rake example RAILS_ENV=test"
end
else
#.... stuff ....
end
end
I didn't check for the correctness of code, but you get the idea, right?