Logowanie zmian w aplikacji

Witajcie.
W aplikacji, którą aktualnie piszę, muszę logować praktycznie każdą zmianę, której użytkownik dokona (i to nie tylko o obrębie edycji modelu user, ale również dodanie, edycja, usunięcie np. artykułu).
Przez chwilkę próbowałem sam coś takiego napisać, ale po chwili stwierdziłem, że można przecież skorzystać z jakiegoś gotowego gemu - i może wyjdzie to nawet na lepsze. Na ruby-toolbox.com znalazłem coś takiego jak acts_as_audited.
Dla modelu user działa świetnie, tj. loguje kto(ip), co(serializuje zmienione pola przed i po edycji) komu(id usera) i co zrobił(create/edit/update/destroy).
Problem się jednak pojawia, gdy próbuję podpiąć to ustrojstwo pod dowolny inny model - kończy się wtedy na zapisaniu do bazy pustego rekordu. Zastanawiam się, czy plugin ten był tworzony tylko do logowania zmian u usera, czy ogólnie modeli - i czy istnieje jakiś lepszy gem/plugin (ważne: musi działać z railsami3) do tego typu zabawy, czy wziąć się za napisanie własnego, czy może grzebać w acts_as_audited.
A może ktoś z Was musiał już wcześniej zmierzyć się z takim problemem, i rozwiązał go w jakiś inny sposób?
Z góry dzięki za odpowiedzi…

Od acts_as_audited o wiele lepiej wygląda timeline_fu, ale ten plugin nie był aktualizowany od roku i najprawdopodobniej nie będzie działać z 3.x. Nie wiem też, jak wygląda sprawa z kompatybilnością jego forków z najnowszymi Railsami.

timeline_fu również lekko trąci myszką… dziwi mnie, że nie ma czegoś nowoczesnego, dobrze napisanego i konfigurowalnego…

Może warto by się zastanowić nad jakąś bazą danych, która wspiera wersjonowanie? W ostatnim projekcie zastanawialiśmy się nad CouchDB, ale ostatecznie zrezygnowaliśmy z wersjonowania na rzecz jakiegoś uproszczonego mechanizmu.

nie jestem pewien czy couch jest odpowiedzią na moje problemy.
Po pierwsze, muszę udostępnić użytkownikowi możliwość wyświetlenia wszystkich zmian, jakie go dotyczą(wszystkie zmiany w aplikacji, jakie on dokonywał + wszelkie zmiany na nim (tzn. na modelu user o jego id) )
Po drugie, aplikacje mam już w dość znaczym procencie gotową, i jak znam życie, będą jakieś jazdy z migracją

My używaliśmy PaperTrail (https://github.com/airblade/paper_trail), co prawda do bardzo małego projektu, i z Rails 2.x, ale widzę że ostatni update z października.

Spróbuj tego, fork firmowany przez Svena Fuchsa więc musi być dobre :wink: https://github.com/svenfuchs/vestal_versions

A, no to co innego. Ja myślałem, że chcesz zrobić coś w stylu timeline’a, jaki jest np. na GitHubie.

po krótkim pomacaniu, papertrail wygląda świetnie. bez problemu działa z railsami3 i na chwilę obecną mam wrażenie, że ma wszystko, czego potrzebowałem - dzięki :wink:
//Edit:
Za szybko odpisujecie - sprawdzę jeszcze vestal_versions :wink:

Muszę tu obalić popularny mit - couchdb nie wspiera wersjonowania.

Stare wersje dokumentów są pozostawiane jedynie w celu zwiększenia wydajności / pomocy w rozwiązywaniu konfliktów replikacji i mogą zniknąć z bazy w każdym momencie.

W każdym razie, moim zdaniem, wykorzystanie bazy danych nosql jest dobrym pomysłem. Może połączenie funkcjonalności dirty railsów i jakiejś szybkiej bazy nosql?

Odkopię temat…

Czy możliwe jest logowanie tego typu zmian przy pomocy Loggera (http://www.ensta.fr/~diam/ruby/online/r … ogger.html) ?

Wymyśliłem, że dopiszę takie coś do Application Controllera

@file = open('activity.log', File::WRONLY | File::APPEND) def log_activity(*args) ActiveRecord::Base.actionLogger = Logger.new(@file) actionLogger.debug(args) end
Jeśli dobrze kombinuję, to jesli będę wywoływał w ramach interesujących mnie ‘eventów’ log_activity (current_usser.name, "zrobił cośtam")
to otrzymam co chciałem. A jeśli nie, to mi się coś wykrzaczy po drodze

tego typu rzeczy nie przechowuje sie w pliku - od tego jest baza danych.

Zależy do czego użyasz tych danych. Taka tabela może szybko urosnąć, jeśli nie potrzebujesz dużej agregacji i wystarczy ci samo sed/awk/grep, a dane są tylko informacyjne (nie używasz ich w żaden sposób do prezentacji aktywności użytkownika) to nie powinieneś ich trzymać w bazie wystarczy fs + logrotate.

Projektując własne rozwiązanie, możnaby użyć powiadomień (?):

http://railscasts.com/episodes/249-notifications-in-rails-3

no ale przecież bazy danych są wprost stworzone do tego, żeby przechowywać dużą ilość informacji(500k rekordów to nie jest jakoś niesłychanie dużo). Poza tym (przynajmniej w moim pytaniu) te dane trzeba było wyświetlić użytkownikowi - wtedy koncepcja pliku niestety upada.

[quote]Projektując własne rozwiązanie, możnaby użyć powiadomień (?):

http://railscasts.com/episodes/249-noti … in-rails-3[/quote]
ja pozostałem przy paper trail - jest w miarę ok, choć nie jest to szczyt marzeń - fajnie by było, gdyby ktoś napisał lepszego plugina do takiego zadania;)

No tak, racja… do tego nie bardzo wiem jak przechwytywac zdarzenia action.save, żeby po nich odpalać swoje logowanie…

Więc poszperałem i oprócz wcześniej przez was podanych linków znalazłem jeszcze dwie rzeczy, ale szczerze mówiąc nie wiem na co dokładnie zwracać uwagę


Chciałbym logować informację o tym kto się loguje i o jakiej porze, oraz kto wykonuje wszelkie zmiany (new/update/delete)…
Myslałem też o zrobieniu triggerów bazodanowych, ale pomijając fakt, ze nie uzyskam dla nich pełnych danych, to chyba nie jest to dobre podejście do problemu.

Ok, wczytałem się trochę i mam pytanie.

Czy decydując się na paper_trail i dodając do każdego modelu, który chce wersjonować, “has_paper_trail” w bazie zostaną stworzone dodatkowe tabele trzymające stare wersje rekordów?
Czy obecna zawartość bazy zostanie jakoś zmieniona, w procesie dodawania papertraila?

W bazie tworzy się tabela Version, która przetrzymuje dowiązania do obiektów + zrzutowane usunięte obiekty.

Pozatym nic sie nie zmienia.

Dziekuję za odpowiedź.
Znalazłem informacje o tej tabeli:

create_table :versions do |t| t.string :item_type, :null => false t.integer :item_id, :null => false t.string :event, :null => false t.string :whodunnit t.text :object t.datetime :created_at
I teraz mam pytanie - jesli chcę stworzyć papertraila dla modelu A i B, to czy dobrze rozumiem, że w “item_type” będe miał nazwę modelu, w “item_id” id elementu w tabeli; a w “object” stan rekordu sprzed operacji?

Item_type i item_id zgadza sie, jednakze zmienna object jest defaultowo uzupelniana tylko podczas akcji update i destroy.

Paper trail rzutuje aktualny obiekt na stringa poprzez: object.attributes.to_yaml