2013-05-22 9 views
7

Ich habe ein Modell in meiner Rails App für ein Bulletin, und wenn es erstellt wird, werden viele der Werte in der Datenbank als serialisierte Hashes oder Arrays gespeichert, auf die später zugegriffen wird. Ich versuche, eine Bearbeitungsansicht für nur einen dieser Hashes zu erstellen, aber ich kann nicht herausfinden, wie ich darauf in meinem Formular zugreifen kann.Wie bearbeitet serialisierte Rails Hashes in einem Formular?

Der Hash sieht wie folgt aus, wenn sie gespeichert:

top_offices = { first_office: "Office Name", first_office_amount: 1234.50, 
second_office: "Office Name", second_office_amount: 1234.50 } 

Und so weiter ... gibt es fünf Büros.

So in der Konsole kann ich die Werte bearbeiten, indem Sie:

bulletin = Bulletin.last 
bulletin.top_offices[:first_office] = "New Office" 
bulletin.top_offices[:first_office_amount] = 1234.00 
bulletin.save 

ich kann nicht herausfinden, wie ein Formular zu machen, die ich richtig diese Werte zuweisen kann. Ich brauche nicht einmal das Formular, um die zuvor gespeicherten Werte zu füllen, weil ich sie jedes Mal komplett ändere, wenn ich das Formular verwende.

Antwort

8

Option 1: Einzelinstanzmethode zu aktualisieren serialisierten Attribut

Soweit ich es nicht möglich, einfach eine serialisierte Attribut direkt aus einem Formular zu bearbeiten.

Wenn ich diese Art von Dingen habe, erstelle ich immer eine Instanzmethode im Modell, die params erhält und die Aktualisierung vornimmt (könnte auch das Speichern tun, wenn ich den Methodennamen mit einem Knall (!) Beende).

In Ihrem Fall ich folgende tun würde:

class Bulletin 

    ... 

    def update_top_offices!(params) 
    params.each do |key, value| 
     self.top_offices[key] = value 
    end 

    self.save 
    end 

    ... 
end 

Option 2: Ein Getter/Setter pro serialisierten Attribut Schlüssel

Auch eine andere Möglichkeit, wenn Sie wirklich ein Formular verwenden wollen, die serialisierte zu aktualisieren Attribut ist ein Getter/Setter wie folgt zu erstellen:

class Bulletin 

    ... 

    def first_office 
    self.top_offices[:first_office] 
    end 

    def first_office=(value) 
    self.top_offices[:first_office] = value 
    end 

    ... 
end 

Aber dann vergessen Sie nicht aktualisierten Werte zu speichern. 3

Optionen: Übergeordnete method_missing

Eine letzte Möglichkeit ist method_missing außer Kraft zu setzen, aber es ist ein wenig komplexer.

+0

Okay. Ich denke, ich werde es mit der ersten Option herausfinden können. Ich bevorzuge wahrscheinlich den zweiten Ansatz, aber ich kann nicht herausfinden, wie es in meinem Kopf funktioniert. Wie verwende ich diese Methoden im Formular? Kann ich einfach ein 'form_tag' und ein paar 'text_field_tag's für': first_office' erstellen, sobald ich diese definiert habe, und an meine Update-Aktion senden? –

+1

Die * _field-Ansichtshelfer suchen nach dem angegebenen Attributnamen für das angegebene Objekt form_for. Wenn Sie also 'form_for @bulletin do | f |' gemacht haben und dann 'f.text_field: first_office', dann ruft der' text_field'-Helfer etwas mit dem Namen 'first_office' auf dem Objekt auf.Es könnte ein Attribut oder eine Methode sein. Das ist der "magische" Teil;) – ZedTuX

5

Hier ist ein Beispiel, das nur über die bestehenden Schlüssel/Wert-Paare in top_offices iteriert und Formularfelder für sie generiert.

<% @bulletin.top_offices.each do |key, value| %> 
    <input name="bulletin[top_offices][<%= key %>]" type="text" value="<%= value %>" /> 
<% end %> 

generiert:

<input name="bulletin[top_offices][first_office]" ... /> 
<input name="bulletin[top_offices][first_office_amount]" ... /> 
# etc. 

Wenn Sie nicht Ihre Benutzer vertrauen, dann können Sie eine Plausibilitätsprüfung auf Werte für top_offices vorgelegt tun wollen.

Verwandte Themen