Vlastný rake task

Ak je potrebné vykonať zmeny alebo opravy nad existujúcimi dátami, vytvorím si rake task. Takýto príkaz potom viem spustiť lokálne, ale aj na serveri. Migrácie alebo seedy mi z viacerých dôvodov na tento účel nevyhovujú. Pozrime sa teda, ako si napísať vlastný rake task.

V rails projekte vytvorím nový súbor lib/tasks/dataset.rake:

namespace :dataset do
  task fix_categories: :environment do
    # Sem ide ľubovoľný kód, toto je iba príklad:
    Category.update_all visible: true
  end
end

Takýto rake task teraz môžem vyvolať príkazom:

$ rake dataset:fix_categories

Čo si treba uvedomiť:

  • Ak príkaz nahodou nejde, skús pred to dať bundle exec, teda celé ešte raz: bundle exec rake dataset:fix_categories
  • Treba dodržať konvenciu, že ak mám namespace :dataset, tak aj názov súboru je taký – dataset.rake. Názov namespacu môže byť ľubovoľný, dataset je iba príklad.
  • Ak púšťam príkaz na serveri, možno treba zadefinovať aj environment a robí sa to takto: rake dataset:fix_categories RAILS_ENV=production
  • Ak chcem spúštanie rake tasku zautomatizovať, prípadne pravidelne opakovať, môžem tak spraviť cez CRON. Odporúčam skombinovať s gemom whenever.
  • Namiesto ručného vytvárania rake task súborov existuje aj generátor, pozri v rails guides.
  • V nových Rails 5 je príkaz rake zjednotený pod príkaz rails. Takže task môžeme spustiť aj ako rails dataset:fix_categories. Pozri tento článok.

Príklad

Ďalší príklad: Keď sme na autozurnal.ta3.com menili URL k obrázkom kvôli CDN, bolo treba v každom článku pomeniť URL adresy za nové. Išlo o 6500 článkov a chcel som na to jeden príkaz, ktorý si pustím v development móde a keď nasadím kód na produkciu, pustím si ho aj tam.

Keďže task :fix_images bude pracovať s modelom Post, pomenujem tak aj súbor a aj namespace vo vnútri:

# lib/tasks/post.rake:

namespace :post do
  task fix_images: :environment do
    Post.find_each do |post|
      puts "Updating ... #{post.title}"
      post.body.gsub!(
        'https://autozurnal-images.s3.amazonaws.com/uploads/ckeditor/pictures',
        'http://d3zhhyfxiecp24.cloudfront.net/uploads/ckeditor/pictures'
      )
      post.save
    end
  end
end

Takýto task sa pozrie do každého článku (v modeli Post) a pomocou gsub nahradí v tele článku (atribút :body) starý prefix za nový.

Task pustím príkazom:

$ rake post:fix_images

Rake tasky sa dajú rovnako použiť aj na seedovanie dát (vytvorenie prvotných dát) a namiesto natívnej podpory rake db:seed a db/seeds.rb, rake tasky sa dajú členiť a každý task spúšťať samostatne. Aj keď záchrana pre seedy existuje v podobe gemu seedbank, tak rake tasky idú a sú podporované bez pridania akéhoľkovek gemu.

A nakoniec, ešte jeden príklad s videom, ktoré zachytáva priebeh rake tasku. Síce iného (jeho kód tu už neuvádzam)), ale pristupuje tiež rovnaku ku každému článku zo stránky autozurnal.ta3.com. V spojení s príkazom puts je to celkom matrixové. Ďakujem za čítanie.