This post originated from an RSS feed registered with Ruby Buzz
by Jonathan Weiss.
Original Post: What to put into Rake tasks
Feed Title: BlogFish
Feed URL: http://blog.innerewut.de/feed/atom.xml
Feed Description: Weblog by Jonathan Weiss about Unix, BSD, security, Programming in Ruby, Ruby on Rails and Agile Development.
As a consultant for Peritor I often review other peoples code. What I often encounter and always address is custom logic in Rake tasks.
Rake is perfect for automating tasks and making calls into your application from the command line. People often use it for doing maintenance, executing periodic jobs, or starting and stopping services. Nothing wrong with that, this is what Rake in Rails apps is for.
What I resent is having all this logic in the Rakefile, either inline in the task body or as a method in the Rakefile.
# Rakefile
task :ping_stale_users do
stale_users = User.find(:all,
:conditions => ["last_login < ? ", Time.now - 3.months])
...
...
stale_users.each do |user|
if user.check_something
user.mail_invite
end
end
end
This is just wrong for the following reasons:
Testing is hard: methods and Rake tasks are hard to test. The environment is hard to create and you may have to shell-out to call rake.
Reusing is hard: you cannot easily reuse this functionality from the console or an admin controller.
POLA: Rakefile are not were people look for domain logic
The solution is simple and yet it seems underused. Just put your domain logic into a model or library and call it from the Rake task. This way it is much easier to test, reuse, and read.
# Rakefile
task :ping_stale_users do
User.ping_stale_users
end
# User.rb
def self.ping_stale_users
stale_users = User.find(:all,
:conditions => ["last_login < ? ", Time.now - 3.months])
...
...
stale_users.each do |user|
if user.check_something
user.mail_invite
end
end
end
Of course the method in the model can be cleaned up a bit more but this is not the point. The point is that we removed domain logic from the Rakefile and made it shorter and easier to understand. The logic is now somewhere where we can test and reuse it.