Page 157 of 171

Archiwizacja modelu czyli moje własne Acts as Archivable

Wczoraj pisząc projekt, wpadłem na pomysł wersjonowania tekstów. Postanowiłem że każda zmiana zawartości musi być równoznaczna ze stworzeniem kopii zapasowej. Funkcjonalność tą postanowiłem wydzielić do pluginu, z racji tego że może przydać się w innych modelach.

Jak to zrealizowałem? Postanowiłem skorzystać z pluginu acts_as_tree. Implikuje to niestety to, że jeśli chcemy skorzystać ze struktury drzewa i backupu to niestety musimy poszukać innego pluginu ;)

Struktura całego mechanizmu ma następującą postać:

Tekst (czy też inny obiekt)

  1. Kopia 1
  2. Kopia 2
  3. Kopia 3
  4. etc

Kopie wykonywane są w momencie aktualizacji modelu. Wykorzystany jest do tego callback before_update.

Interfejs pluginu składa się z trzech metod instancyjnych i jednej klasowej. Metody instancyjne to:

  • backup! - Robi kopie samego siebie do archiwum
  • restore!(id) - przywraca kopię o wybranym id lub też jesli wywołane na kopii to przywraca kopię z której wywołaliśmy
  • cleanup! - usuwa wszystkie kopie poza najnowszą

Metoda klasowa:

  • cleanup! - usuwa wszystkie kopie ze wszystkich elementów, pozostawiając tylko po 1 na element

Problemem na jaki natrafiłem, przy tworzeniu tego pluginu, był Paperclip. Wywołując metodę clone lub po prostu:

target.update_attributes(source.attributes)

Obiekt paperclipa nie było kopiowany. Aby to obejść zastosowałem inne rozwiązanie które wykrywa czy dany obiekt posiada w bazie elementy charakterystyczne dla paperclipa, czyli:

  1. _content_type
  2. _file_size
  3. _file_name

Na podstawie przedrostka rozpoznaje jak te obiekty się nazywają, następnie wywołując dla nich metodę przypisania:

        paperclip_obj.each { |obj|
          sym = "#{obj}=".to_sym
          target.send(sym, self.send(obj.to_s))
        }

Dzięki czemu, kopiowane są wszystkie atrybuty oraz obiekty paperclipa (niezależnie od ich ilości). Dzięki czemu archiwizujemy nie tylko sam przykładowo tekst, ale i powiedzmy miniaturkę. Oczywiście ma to swoje minusy - ilość miejsca zajmowanego przez kopie rośnie bardzo szybko. Na szczęście jest wyżej wspomniana metoda cleanup!

A oto jak zastosować plugin:
Przykładowa klasa:

class CoolClass < ActiveRecord::Base
    acts_as_tree
    acts_as_archivable
end

Następnie zrobienie 10 kopii w odstępach 1sekundowych:

    model = CoolClass.create
    10.times {
      model.content += "a"
      sleep(1)
      model.save
    }

I już mamy nasz model + kopię zapasową każdej wersji.

Teraz przywróćmy powiedzmy drugą wersję (czyli tą "prawie" najdawniejszą):

model.children.second.restore!
# Musimy przeładować model bo zmieniają się jego parametry
model.reload

Z racji tego że zmieniają się parametry obiektu w bazie, musieliśmy wykonać przeładowanie.

Przywrócenie można zrobić także na drugi sposób, wywołując metodę restore! na obiekcie w stosunku do którego chcemy wykonać przywrócenie:

model.restore(model.children.second.id)

Jeśli tak wywołamy przywracanie, nie musimy wywoływać metody reload, ponieważ wywoływana jest automatycznie z poziomu metody restore!

Aby wyczyścić kopie zapasowe, pozostawiając tylko najnowszą, wykonamy:

model.cleanup!

Lub też jeśli chcemy posprzątać wszystkie modele:

CoolClass.cleanup!

Tyle :) aby wyświetlić kopie zapasowe, wystarczy przeiterować dzieci w taki sposób:

model.children.each {
# Jakiś kod :)
}

Plugin do pobrania tutaj: acts_as_archivable

Netbeans 6.8 on Ubuntu + problems with hanging SVN

After months of using RapidSVN, I've decided to go back and use Netbeans integrated SVN client. However it started to hang my Netbeans IDE when I've been committing stuff into repo. After 5-6 attempts Netbeans finally committed stuff but come on - 6 IDE restarts to make one commit? Hell no!

Go into:

Tools --> Options --> Miscellaneous -->Versioning --> Subversion

Find: Path to the SVN executable File: and change it into:

/usr/bin

Restart your IDE and use it with SVN client without any hangs. You should also disable any plugins you are not using.

Copyright © 2025 Closer to Code

Theme by Anders NorenUp ↑