What is a rake task? ● Just a script to run at any time in a console ● Common Rails tasks: ○ rake db:reset, rake db:create, rake db:migrate ○ rake -T ○ rake routes ● Custom task: desc 'Rake task description' task :name_of_task do # Your code goes here end
My list of the things to consider ● Size of .rake file ● Idempotency ● Tracking progress ● Logging the work ● Isolated structure ● Testing ● The performance
Keep .rake file as small as possible namespace :mailchimp desc 'Import users from Mailchimp' task :import_users do puts 'Importing users from Mailchimp' result = Mailchimp::ImportUsers.call puts "Successfully imported #{result} users!" end end
Idempotency ● It’s important on cleanups and migrations ● Can be easily fulfilled with: ○ a good query ○ modifying the input file ○ omitting already created data
Tracking progress ● The task executor needs to know the current status of the task ● Show anything ○ from dots ○ to printing a line for each processed item ● Or use a gem ProgressBar:
ProgressBar gem namespace :cleanup desc 'Cleanup bad fees' task :fix_bad_fees do query = Cleanup::FixBadFees::Query.call progress_bar = ProgressBar.create( title: 'Fixing bad fees by adding a discount', total: query.count ) # ... end end namespace :cleanup desc 'Cleanup bad fees' task :fix_bad_fees do # ... result = Cleanup::FixBadFees::Task.call(query: query) do progress_bar.increment end puts "Successfully fixed #{result} fees!" end end
ProgressBar gem class Cleanup::FixBadFees::Task def self.call(*args, &block) new.self(*args, &block) end def call(query:) query.find_each do # Fix bad fees yield if block_given? end end end
Logging ● Who performed the task? When? Why? ● Log the action ○ Notes ○ Audit trail ○ History events ● Log the task’s execution ● Include the executor ○ TASK_EXECUTOR=jon.snow@westeros rake kill_undead
Testing custom rake tasks ● Automated tests class for each PORO class used in a rake task ● No automated tests for .rake file, rely on manual testing ● Don’t be lazy
Performance ● Predict the scale at the very beginning ● Define bottlenecks ○ Reading from large file or from multiple database tables ○ Calling external services ○ Saving many rows to the database ● Use database close to production (locally, staging)