Ostatnio przeglądając kod Redmine'a natknąłem się na fajny kawałek kodu. Nigdy się nad tym nie zastanawiałem i w zasadzie, nigdy zbytnio nie potrzebowałem.
Jak za pomocą linka, zaktualizować wybrany atrybut instancji modelu?
Zazwyczaj do aktualizacji danej instancji korzystam z edit'a oraz forma odpowiedniego do tego. Dzisiaj jednak nadarzyła się ku temu okazja.
Mam w systemie model o nazwie Cron który odpowiada za cykliczne odpalanie komend/metod które są w nim yieldowane. Np:
Cron.backup{ # Wykonaj nową kopię zapasową Backup.create # Usuń stare kopie zapasowe Backup.sweep(Setting::Cron.backup_lifetime) }
Powyższy "cron" o nazwie backup odpala się co 7 dni wykonując kopię zapasową systemu. Usuwa przy okazji kopie starsze niż backup_lifetime. Z ciekawostek warto wspomnieć, że dzięki "fajności" Rubiego, mogłem napisać sobie w bardzo prosty sposób własne mapowanie, nie po kolumnach a po wierszach. Właśnie dzięki temu metody modelu Cron są generowane dynamicznie. Ale to jest temat na oddzielną notkę.
Wracając do sedna sprawy. Model Cron korzysta z pola updated_at aby określić kiedy Cron był ostatnio odpalany. Jeśli było to dawniej niż zadana w instancji częstotliwość - uruchamia kod yieldowany.
Problem pojawił się kiedy chciałem dorobić "wymuszone" odpalenie instancji Crona. Najprostszą metodą do zrobienia tego, było wyedytowanie updated_at i nadanie mu wartości np. 1.year.ago. Rozwiązać można to było tworząc metodę w stylu force. Nie byłoby to jednak zgodne z RESTem. Bardzo fajnie rozwiązano to w Redminie. Mianowicie tworzony jest link_to który zawiera wszelkie potrzebne informacje. Jak taki link wygenerować? Bardzo prosto:
link_to "Wymuś", cron_path(task, 'cron[updated_at]' => 1.year.ago), :method => :put
Metoda link_to stworzy nam link który zostanie zrealizowany przez metodę update na instancji modelu Cron. Dzięki dodaniu parametru:
'cron[updated_at]' => 1.year.ago
informujemy Railsy, że ma naszemu cronowi przypisać datę ostatniego wykonania na rok wstecz. Dzięki temu, przy najbliższej możliwej okazji, kod z Crona zostanie zrealizowany.
Leave a Reply