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.