2017-05-17 5 views
0

Ich versuche, eine Sicherungstabelle von users, archived users genannt, zu erstellen. Er erstellt den ArchivedUser, indem er einen Hash der aktuellen Benutzerattribute (self) annimmt und ihn in self.id als user_id zusammenführt.Erstellen oder Aktualisieren von Datensatz für ArchivedUser

Wenn ein Benutzer wieder aktiviert wird, bleibt sein Datensatz als ArchivedUser weiterhin in der ArchivedUser Tabelle. Wenn der Benutzer ein zweites Mal gelöscht wird, sollten alle geänderten Attribute aktualisiert werden.

Derzeit führt es einen Überprüfungsfehler: Validation failed: User has already been taken, wie die self.id bereits in der Tabelle ArchivedUser existiert.

Was ist eine bessere Möglichkeit, ein Objekt zu behandeln, wenn Sie ein vorhandenes Objekt aktualisieren, wenn möglich, oder einen neuen Datensatz erstellen, wenn dieser nicht existiert. Ich bin mit Rails 4 und haben find_or_create_by versucht, aber es wirft einen Fehler

Mysql2::Error: Unknown column 'device_details.device_app_version'

, die ungerade ist, wie die Spalte in beiden Tabellen vorhanden ist und nicht geändert hat bekommen.

Benutzer löschen Methode

# creates ArchivedUser with the exact attributes of the User 
    # object and merges self.id to fill user_id on ArchivedUser 
    if ArchivedUser.create!(
    self.attributes.merge(user_id: self.id) 
) 

Vielen Dank für einen Blick nehmen!

Antwort

0

Wenn Ihre archived_users Tabelle wirklich wird als Backup für Benutzer handeln und keine zusätzliche Funktionalität hinzufügen, würde ich das ArchiveUser Modell Graben und einfach eine archived boolean auf das User Modell hinzufügen zu sagen, ob der Benutzer archiviert wird.

Auf diese Weise müssen Sie sich nicht damit beschäftigen, ein Objekt in eine andere Tabelle zu verschieben und in einen Lösch-Callback einzuhaken.

Wenn jedoch Ihr ArchiveUser Modell eine andere Funktionalität bietet als User, wäre eine andere Option single table inheritence zu verwenden, um den Benutzertyp zu unterscheiden. In diesem Fall könnten Sie haben User gelten für alle Benutzer, und dann zwischen einem Benutzer Wesen, zum Beispiel zu unterscheiden, ein ActiveUser oder ein ArchivedUser.

Dies nimmt mehr Setup und kann ein wenig verwirrend sein, wenn Sie nicht mit STI gearbeitet haben, aber es kann nützlich sein, wenn zwei ähnliche Modelle nur geringfügig abweichen müssen.


aber sagen, dass, wenn Sie Ihre aktuellen Einstellungen behalten wollen, glaube ich, ein paar Fragen, die ich mit Ihrem Code gibt es zu sehen:

  1. Wenn Sie ein Objekt von einem gehen erstellen existierendes Objekt, es ist eine gute Praxis, duplicate the object (dup). Auf diese Weise wird die id nicht automatisch festgelegt und kann automatisch inkrementiert werden.

  2. Wenn Sie wirklich den User Datensatz aus der Datenbank gelöscht haben, gibt es keinen Grund, eine Referenz zu seinem id zu speichern, weil es weg ist. Aber wenn Sie tatsächlich nicht den Datensatz löschen, sollten Sie auf jeden Fall verwenden nur ein boolean-Attribut, um zu bestimmen, ob der Benutzer aktiv ist oder archiviert werden.

  3. Ich habe nicht genug Kontext hier, warum find_or_create_by nicht funktioniert, aber wenn es der Fall wäre, dann würde ich es so einfach wie möglich halten. Verwenden Sie nicht alle Attribute, sondern nur die konsistenten (wie id), von denen Sie wissen, dass sie das richtige Ergebnis liefern.

  4. if ArchivedUser.create! # ... ist problematisch. Der Knall nach dem Erstellen (d. H. create!) wird einen Fehler ausgeben, wenn der Datensatz nicht erstellt werden konnte, was die if sinnlos macht. Verwenden Sie also entweder if, wenn Fehler nicht ausgegeben werden sollen, und möchten Sie die Bedingung behandeln, in der der Datensatz nicht erstellt wurde. Oder verwenden Sie create! ohne if, wenn Sie einen Fehler werfen möchten.

Verwandte Themen