2010-12-17 7 views
9

Gibt es eine Möglichkeit, eine benutzerdefinierte Serialisierung für Felder in Rails zu haben, eine Methode, die ausgeführt wird, wenn ein Feld gespeichert und geladen wird, um von/in eine Zeichenfolge zu konvertieren, die letztendlich in der Datenbank gespeichert wird .Benutzerdefinierte Serialisierung für Felder in Rails

Speziell was ich tun möchte, ist ein Feld des Typs Symbol wie Geschlecht, mit möglichen Werten: männlich und: weiblich speichern "männlich" und "weiblich" in der Datenbank. Es gibt einige Workarounds, wie:

def gender 
    read_attribute(:gender).try(:to_sym) 
end 

aber das lässt obj.attributes unverändert, so ist es eine undichte Abstraktion.

Antwort

10

Sie es 3.1 in Rails tun. Das Objekt, das Sie serialisieren möchten, muss auf die Methoden load und dump antworten.

Hier ist ein Beispiel für die Serialisierung einer Zeichenfolge in Base64.

class User < ActiveRecord::Base 
    class Base64 
    def load(text) 
     return unless text 
     text.unpack('m').first 
    end 

    def dump(text) 
     [text].pack 'm' 
    end 
    end 

    serialize :bank_account_number, Base64.new 
end 

Weitere Informationen finden Sie unter: http://archives.edgerails.info/articles/what-s-new-in-edge-rails/2011/03/09/custom-activerecord-attribute-serialization/index.html

+3

Der Detaillink scheint jetzt leider tot zu sein. Gab es einen Grund, warum Sie 'dump' und' load' als Instanzmethoden definiert haben und eine neue Instanz in 'serialize' übergeben haben? Anstatt sie als Klassenmethoden zu definieren und die Klasse in 'serialize' zu ​​übergeben? Ich versuche nur zu verstehen, danke! – plainjimbo

+0

Ich mache hier eine wilde Aufnahme im Dunkeln, aber es sieht so aus, als ob die ActiveRecord-Serialisierung jedes Objekt verwendet, das auf ': dump' und': load' reagiert. Also, nein. Es gibt keinen Grund, warum dies Instanzmethoden im Gegensatz zu Klassenmethoden sind. – RyanScottLewis

0

können Sie die Modelle to_xml für ein Modell definieren, und es wird tun, dass http://api.rubyonrails.org/classes/ActiveRecord/Serialization.html

seine mögliche Marshall.dump und stellen auf diese Weise zu definieren, denke ich, aber es ist etwas zu suchen in

+0

Ich spreche nicht über die Serialisierung eines ganzen Modells zu einer Zeichenfolge, sondern Serialisierung eines einzelnen Feldes zu einer Zeichenfolge in der Datenbank gespeichert werden. – Pablo

0

Sie könnte serialize Methode innerhalb des Modells verwenden. Beziehen Sie sich auf zu diesem Link: (. Ps Suchbegriff "serialisiert" auf dieser Seite; D) http://api.rubyonrails.org/classes/ActiveRecord/Base.html

Kurz gesagt, können Sie dies tun:

class YourModel < ActiveRecord::Base 
    serialize :db_field 
end 

Rails automatisch das Feld serialisiert würde vor dem Speichern zur Datenbank und deserialisieren sie nach dem Abruf aus der Datenbank.

+1

Das Problem dabei ist, dass es in Yaml umgewandelt wird, was die Verwendung der Daten in Abfragen schwieriger macht, wenn nur ein einfaches Symbol in eine String-Konvertierung gespeichert wird. Das habe ich gemeint, indem ich "männlich" und "weiblich" in der Datenbank gespeichert habe, also statt "---: männlich" und "---: weiblich"). – Pablo

0

gut für nur Männer/Frauen könnten Sie tun, nur eine Boolesche Spalte wie männlichen und wenn es falsch ist davon ausgehen, dass weibliche gemeint, Wrapper-Methoden für sie

def female? 
    return !self.male? 
end 
+0

Dies ist nur ein Beispiel, ich möchte mehr als zwei Symbole speichern. Probieren Sie es mit männlich, weiblich, unbekannt und versteckt. – Pablo

4
def whachamacallit 
    read_attribute("whachamacallit").to_sym 
end 
def whachamacallit=(name) 
    write_attribute("whachamacallit", name.to_s) 
end 

speichert sie als Stiche in dem hinzufügen Datenbank, aber extrahieren Sie sie als Symbole, wenn Sie sie herausziehen, dann konvertieren Sie zurück, bevor Sie speichern. würde mit einer beliebigen Anzahl oder Kombination von Zeichenfolgen/Symbolen arbeiten.

es nur ein paar Auserwählte zu begrenzen

validates_inclusion_of :whachamacallit, :in => [ :male, :female, :unknown, :hidden ] 
+0

Ich habe über diese Lösung nachgedacht, was mir nicht gefällt ist, dass wenn ich mir obj.attributes anschaue, das Feld offensichtlich eine Zeichenkette anstelle eines Felds ist und ich weiß, dass es mich zurückschlagen wird, wenn ich es weniger erwarte es. – Pablo

0

Wir haben gerade ein Juwel veröffentlicht (AttributeHelpers), das genau dies. Haftungsausschluss: Ich bin ein Betreuer für das Juwel.

Es ermöglicht Ihnen, attr_symbol :gender in Ihrer Klassendefinition aufzurufen und die Serialisierung geschieht automatisch.

Verwandte Themen