2016-05-27 5 views
0

Ich habe eine YAML-Datei, die in einer Reihe von Fragen auf meine Schienen DB lädt. Gelegentlich mache ich Änderungen an der Question.yml-Datei (zB möchte ich den Fragetext etwas ändern), und aufgrund der Art, wie ich diese in ein Rails-Frage-Modell lade, lehnt die DB das Update ab (weil es schon da ist eine Frage in meinem DB mit dieser ID). Ich mache im Moment häufigere Änderungen an den Fragen und möchte, dass sie flexibler sind, also kann ich die YAML-Datei vor dem Hochladen prüfen, um zu sehen, ob z. die letzte gespeicherte Zeit hat sich geändert, dann nur die DB aktualisiert, wenn das passiert ist?Kann ich überprüfen, ob eine YAML-Datei vor dem Laden in Rails aktualisiert wurde?

Ein Beispiel Frage:

- id: 1 
    question_text: Why does this company need to buy your products or services? 
    answer_type: Text Field 
    next_question_id_yes: 2 
    next_question_id_no: ~ 
    collectable: ~ 
    sale_stage: Need 

Wie die aktuell Datei in die DB geladen wird:

File.open("#{Rails.root}/config/initializers/questions.yml", 'r') do |file| 
    YAML::load(file).each do |record| 
    Question.create(record) unless Question.exists?(record) 
    end 
end 

Diese Methode ist nicht nur schnell, wenn der Datensatz bereits vorhanden ist zu prüfen (wie das existiert nur Methode? überprüft die ID der Frage), aber nutzlos, da ich die Frage IDs nicht ändere - nur die anderen Felder unten in der Datenbank. Wie Sie sehen können, brauche ich die IDs, um statisch zu bleiben, da dies Teil eines Entscheidungsbaums ist und jede Frage wissen muss, welcher Frage id folgt (abhängig von dem Antworttyp und der Antwort).

Zeit, wenn ich versuche, die YAML-Datei zu aktualisieren und dann verwenden, die in der App ich die folgende Fehlermeldung erhalten:

ActiveRecord::RecordNotUnique: PG::Error: ERROR: duplicate key value violates unique constraint "questions_pkey" 
DETAIL: Key (id)=(1) already exists. 
: INSERT INTO "questions" ("answer_type", "created_at", "id", "next_question_id_yes", "question_text", "sale_stage", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" 

Gibt es irgendeine Weise, die ich den Status der YAML-Datei speichern kann, selbst, und wenn es wurde aktualisiert, dann kann ich einfach alle alten Aufzeichnungen zerstören und die neue YAML-Datei als Evangelium hochladen?

P.S. Wenn das aus irgendeinem Grund eine dumme Idee ist, kann ich nicht darüber nachdenken, bitte lass es mich auch wissen. Es scheint eine Verschwendung von Ressourcen zu sein, aber ich erwarte, dass ich in Zukunft weitere Fragen hinzufügen und für die Benutzer aktualisieren werde. Daher brauche ich diese Flexibilität, ohne dies manuell in der Rails-Konsole vornehmen zu müssen.

Antwort

1

Verwenden find_or_initialize_by

File.open("#{Rails.root}/config/initializers/questions.yml", 'r') do |file| 
    YAML::load(file).deep_symbolize_keys.each do |record| 
    q = Question.find_or_initialize_by(id: record[:id])) 
    q.assign_attributes(record.except(:id)) 
    q.save! if q.new_record? || q.changed?  
    end 
end 

Obwohl auf lange Sicht ist es wahrscheinlich viel laufen einfacher, nur eine grundlegende CRUD-Controller zu erstellen, so dass Sie die Datensätze über eine GUI bearbeiten können (oder einen Praktikanten bekommen, es zu tun). ..

+0

Danke - aber die Zeile 'q.save! wenn q.new_record? || q.changed? 'wirft immer noch denselben doppelten Schlüsselwertfehler auf. Irgendwelche Ideen warum? – Zoinks10

+0

Hmm, geht 'q = Question.find_or_initialize_by (id: record [: id]))' einen Datensatz finden? – max

+0

Auch das Festcodieren der IDs in Ihre YAML-Datei kann etwas riskant sein, da IDs von der Datenbank generiert werden. – max

Verwandte Themen