Using Rake to call an external script is quite straightforward: you can simply load it, or call “system”, or “exec”. By the same token, using ActiveRecord classes in a Rake task is easy: you just need to state your task depends on the environment (with “=> :environment”, as shown here).
Where it gets interesting is having an external script that can be used as a standalone, or called from within a Rake task. In my case, I wanted a script to load data from a file that would use ActiveRecord if possible (since it’s much faster), and fallback to Mechanize (to upload the data via the web forms).
The Rake task
Download the full file here.
First, on line we depend on the environment to make ActiveRecord classes available within the task:
task :load => [:environment] do |task|
But before loading the external script on line 15, we call each ActiveRecord class once (lines 10 through 12). Without this step, the classes aren’t actually loaded, and won’t be available from within the external script.
As I said, I wanted to use ActiveRecord, but fall back on Mechanize (using the web forms) to upload the data. How do we achieve this? By checking for the ActiveRecord classes we want to use:
def watch_exists?(case_number) if defined? Watch Watch.find_by_case_number(case_number) else @a.get('http://localhost:3000/watches') do |watch_index_page| return true if watch_index_page.link_with(:text => @case_number) end end end
If the ActiveRecord class we need is defined, we use it, otherwise, we leverage Mechanize to do the work. This simple trick allows us to have a script that can be called from with a Rake task, or directly (e.g. from a shell).