2009-08-25 6 views
0

In meiner Anwendung, diese „Planer“ (im Wesentlichen Artikel Ideen) folgt vorgegebene Vorlagen, in Markdown geschrieben, mit einigen spezifischen hier Syntax:generierte String wird nicht in der Datenbank speichern ... aber am Ende „A“ heftet und es wird

Please write your answer in the following textbox: [...] 

Please write your answer in the following textarea: 
...So here, on line, you should write one thing. 
...Here, on line 2, you should write another. 
... 
... 
... 

Wesentlichen ist [...] eine Texteingabe, und eine Gruppe von Linien mit ... beginnen, eine TextArea-. Das ist nicht wirklich das Problem - es ist nur zu erklären, was ein Teil dieses Codes tut.

Auf Aktionen new und edit wird der Standardplaner Form dargestellt, mit den richtigen Feldern basierend auf der Vorlage (für new) oder aktuelle Planer Körper (für edit). Beim Speichern werden die Felder der Vorlage mit params [: fields] ausgefüllt, und der resultierende Markdown wird als Körper des Planers gespeichert. Ich hoffe, dass der Code nun folgen kann, wenn man diesen Kontext kennt. Es wird nur der relevante Controller-Code bereitgestellt, und es wird make_resourceful verwendet.

class Staff::PlannersController < StaffController 

    make_resourceful do 
    actions :all 

    before :create do 
     find_planner_format 
     if @planner_format 
     current_object.body = fields_in_template @planner_format.body 
     else 
     flash[:error] = 'Planner format not found!' 
     redirect_to staff_planners_path 
     end 
     current_object.user = @current_user 
    end 

    before :update do 
     current_object.body = fields_in_template(current_object.body) 
    end 
    end 

private 

    def fields_in_template(template) 
    fields = params[:fields] || {} 
    if fields[:inline] 
     template.gsub! /\[\.\.\..*\]/ do 
     "[...#{fields[:inline].shift}]" 
     end 
    end 
    if fields[:block] 
     template.gsub! /^\.{3}.*(\n\.{3}.*)*$/ do 
     fields[:block].shift.split("\n").collect { |line| 
      "...#{line}" 
     }.join("\n") 
     end 
    end 
    current_object.body = template 
    end 

end 

Und nun, das Geheimnis: in der update Aktion, Veränderungen des Körpers werden nicht gespeichert. Nach dem Debuggen, habe ich festgestellt, dass das Problem nicht nur in current_object.save nicht liegen, da das, was der folgenden before :update Code tut man erwarten würde:

before :update do 
    current_object.body = 'test string' 
end 

In der Tat, auch wird dies das erwartete Ergebnis:

before :update do 
    current_object.body = fields_in_template(current_object.body) + 'a' 
end 

So, jetzt die Frage: Warum ist Rails so hartnäckig, dass es nicht das Ergebnis der Funktion speichern - und auch dann nur, wenn es von update kommt? Mehr Debugging zeigte, dass das Objektattribut gesetzt ist und sogar behauptet, erfolgreich zu speichern, aber reload das Objekt nach dem Speichern kehrt die Änderungen zurück.

Zuerst sah es aus wie die resultierende Zeichenfolge nur einen „vergifteten“ Variable der Art war, und dass die Zeichenfolge Wiederaufbau von „a“ entfernt, dass seltsamer Zustand anhängt. Der folgende Code, der ein "a" hinzufügen und es erneut entfernen sollte, konnte jedoch nicht gespeichert werden.

before :update do 
    new_body = fields_in_template(current_object.body) + 'a' 
    new_body.slice! -1 
    current_object.body = new_body 
end 

Das ist nur seltsam für mich. Was mache ich hier falsch, und was kann ich eventuell noch weiter machen? (Oder, wenn Sie geschehen, um sofort meinen Fehler zu sehen, würde so schön sein, auch ...)

EDIT: Nach SQL-Protokollen überprüft (nicht sicher, warum ich nicht diesen früher zu tun glaubte), es Scheint so zu sein, dass Rails das neue body-Attribut nicht als tatsächlich anders zu erkennen anerkennt, obwohl das Überprüfen der Zeichenfolge im Debugger dies bestätigt. Daher führt Rails nicht einmal eine UPDATE Abfrage aus, sofern nicht etwas anderes geändert wird. In diesem Fall ist body nicht enthalten.

+0

Warum fügen Sie nicht etwas Protokollierung hinzu, um zu sehen, was gespeichert wird? – klochner

+0

Ich würde auch current_object.body zu einem virtuellen Attribut ändern – klochner

Antwort

1

Verstanden! Manchmal hilft es nur, die Frage laut zu stellen ...

Der Deal ist, ich hatte vergessen, dass, wenn current_object.body zu fields_in_template übergeben wurde, es durch Referenz weitergegeben wurde. Als solche, alle gsub! Methoden wurden direkt auf current_object.body ausgeführt, so Rails erkannte keine wirklichen "Änderungen" bis zu dem Zeitpunkt, als ich Körper auf, was gerade festgelegt wurde.

Die Lösung:

def fields_in_template(template) 
    template = template.dup 
    # ... 
end 

Danke, dass ich mir reden, und Mission erfüllt!

+0

Using gsub! und unter! auf irgendwelche Parameter ist normalerweise genau aus diesem Grund gefährlich. Im Zweifelsfall klonen Sie mit Objekt # dup oder verwenden Sie verkettete gsub-Aufrufe. – tadman

0

Ich bin kein Programmierer Rubin sondern wirkt sich das Hinzufügen ein ‚a‘ den Typ der Variablen Zeichenfolge konvertieren? Vielleicht ist Ihre Variable vom falschen Typ, ohne 'a' hinzuzufügen.

+0

Es ist mir aufgefallen, aber ich habe den Debugger eingecheckt - es ist ein String =/ – Matchu

Verwandte Themen