HASH czy JSON

Postanowiłem zorganizować w swojej apce dziennik wpisów.
Wymyśliłem, że dane wprowadzane przez użytkownika (lub aktualizacje) będę zapisywał do jednej z kolumn “dziennika wpisów” jako hash.
I tak oto wpisuję:
Po akcji create dla przykładowego modelu Customer tworzę:

@customer.attributes.to_hash

co daje coś takiego:

my_hash = {"id"=>67793, "name"=>"Kowalski", "given_names"=>"Jan", "birth_date"=>Sun, 06 Jul 1999, "note"=>"", "user_id"=>1, "created_at"=>Wed, 07 Oct 2015 22:11:41 CEST +02:00, "updated_at"=>Wed, 07 Oct 2015 22:11:41 CEST +02:00}

a po przykładowej zmianie wartości w kolumnie “note”, po akcji update mam:

@customer.previous_changes.to_hash

{“note”=>["", “Test”], “updated_at”=>[Wed, 07 Oct 2015 22:11:41 CEST +02:00, Wed, 07 Oct 2015 23:08:44 CEST +02:00]}

Teraz chciałem “po ludzku” przedstawić to, więc

my_hash.each do |k,v|
  puts "#{k} = #{v.to_s}"
end

ale wywala mi błąd na polach typu “Date”

Pytania:

  1. Czy Waszym zdaniem dobrze wpisuję tego hasha do bazy?
  2. Co robię źle, że wywala mi błąd:

syntax error, unexpected tCONSTANT, expecting =>
…"=>1, “created_at”=>Wed, 07 Oct 2015 22:11:41 CEST +02:00, "…

?

A może - Waszym zdaniem - warto to zapisywać do bazy w innym formacie?

Podstawowe pytanie: dlaczego chcesz to zapisać jako hash?

Tabelka przechowująca dane ma strukturę:

create_table :works do |t|
  t.references :trackable, polymorphic: true, index: true
  t.string :trackable_url
  t.references :user, index: true
  t.string :action
  t.text :parameters

  t.timestamps null: false
end

Gdzie trackable odnosi się do “śledzonych” tabel.
np.:

class Work < ActiveRecord::Base
  belongs_to :trackable, polymorphic: true
  belongs_to :user

class Customer < ActiveRecord::Base
  has_many :works, as: :trackable

Dzięki takiemu rozwiązaniu mogę łatwo wyświetlać historię wpisów

cust = Customer.first
cust.works

… I podpatrując trochę inne rozwiązanie (np. PublicAtvities) pomyślałem, o rozwiązaniu polegajacym na wrzucaniu wszystkich (lub zmienionych) attributes do jakiejś jednej kolumny.

Pytasz dlaczego w formacie hash…
Hmm… Sądziłem, że tak będzie najłatwiej i najprościej to później wyświetlać w “ludzkiej” postaci, by mieć listę typu:
nazwisko = Kowalski
imię = Jan

Jak zapewne zauważyłeś, samemu mam wątpliwości, czy dokonałem słusznego wyboru.
Teraz sądzę, że lepszym pomysłem byłoby as_json() …ale jeżeli masz jeszcze lepsze pomysły, to naprawdę jestem otwarty na wykonanie zmian w mojej apce. :slight_smile:

Mam wrażenie, że trochę przekombinowane. Ale jak coś już musisz zapisać w bazie i używać jako hash to w Rails jest to wbudowane przez metodę serialize.

http://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Serialization/ClassMethods.html
http://rubyjunky.com/rails-activerecord-serialize.html

Może i trochę przekombinowane, ale zostawiam sobie furtkę, by w przyszłości dodać prostą funkcję “Przywróć dane z dnia…” itd. (oczywiście funkcja prosta, a nie uwzględniająca zmiany struktur lub relacji, itd)

Zdecydowałem się zmienić format zapisywanych danych na JSON
Zabrałem się już za gem “active_model_serializers”, gdyż mam w kilku miejscach wykorzystywany format JSON i poczytałem, że działa to o wiele wydajniej niż wbudowany JBuilder ale przy okazji trafiłem na rafę.

Nie wiem jak w plikach xxx_serializer wstawiać dodatkowo zdefiniowane atrybuty, których definicje mam w modelu.

np.
Customer < ActiveRecord::Base

def fullname
“#{name} #{given_names}”
end

wykorzystując jbuildera było prosto:
np.: /views/customer/show.json.jbulder

json.extract! @customer, :id, :name, :given_names, :fullname

a tutaj już to nie działa…więc znowu nurkujemy do tutków i dokumentacji…

Blad ktory masz dotyczy poprawnosci skladni. Data powinna by zamknieta w ‘’.

Druga sprawa - z jakiej bazy danych korzystasz ? W Postgresie jest pole typu JSON i wszystko jest duzo prostsze - http://edgeguides.rubyonrails.org/active_record_postgresql.html

Wiem, że Postgress ma taki typ danych ale apka ma być “prosta” :smiley: :smiley: :smiley: w przenoszeniu na ewentualny MySQL

Może użyjesz po prostu jakiegoś istniejącego rozwiązania typu paper_trail. Działa spoko, używa tego mnóstwo osób i jest niezależne od bazy danych, bo stoi bezpośrednio na abstrakcji ActiveRecord. Ja bym nie wyważał otwartych drzwi.

Wiesz…To jest podobne do dyskusji o wyższości świąt Bożego Narodzenia nad Wielkanocnymi. :wink:

Ja posłuchałem tej rady:

…i chwalę to sobie.
Nauczyłem się znowu czegoś i dostosowałem rozwiązanie dokładnie do swoich potrzeb. Ma to oczywiście swoje konsekwencje w tym, że muszę ileś tam linijek kodu samemu wyklepać lub Was się pytać o jakieś rozwiązania, ale jak to mawiają “niczego nie ma za darmo” :smile:

Tak, czy inaczej mam już te dane w postaci JSON i teraz myślę tylko, by to ładnie zaprezentować, bo nie wiedzieć dlaczego :wink: nie wszyscy użytkownicy lubią oglądać w takiej postaci:
{“id”:123, “name”:“Kowalski”, …}