Frage

Ich habe in den letzten paar Stunden zu kämpfen darüber nachzudenken, welchen Weg ich gehen sollte. Ich habe eine Mitteilung Modell. Bis jetzt habe ich eine NOTIFICATION_TYPE Spalte verwendet, um die Arten zu verwalten, aber ich denke, es wird besser sein separate Klassen für die Arten von Benachrichtigungen zu erstellen, wie sie sich anders verhalten.

Im Moment gibt es drei Wege, Benachrichtigungen können versandt erhalten: SMS, Twitter, E-Mail

Jede Meldung würde:

id
subject
message
valediction
sent_people_count
deliver_by
geotarget
event_id
list_id
processed_at
deleted_at
created_at
updated_at

Scheint, wie STI ein guter Kandidat ist richtig? Natürlich / SMS Twitter keinen Gegenstand haben und Twitter wird keine sent_people_count, valediction haben. Ich würde sagen, in diesem Fall, dass sie den größten Teil ihrer Felder teilen. Doch was ist, wenn ich ein „reply_to“ Feld für twitter und ein boolean für DM hinzufügen?

hier Mein Punkt ist, dass gerade jetzt STI macht Sinn, aber dies ist ein Fall, in dem ich mich in der Zukunft nicht nur beginnend mit MTI werden kann treten?

Um die Dinge zu komplizieren, ich mag ein Newsletter-Modell, das eine Art von Benachrichtigung ist aber der Unterschied ist, dass es nicht event_id oder deliver_by verwenden wird.

konnte ich alle Subklassen der Mitteilung siehe etwa 2/3 der Benachrichtigungsbasisklasse Felder verwenden. Ist STI ein Kinderspiel, oder soll ich MTI verwenden?

War es hilfreich?

Lösung

die begrenzte Informationen gegeben, würde ich Stick mit STI sagen.

Die entscheidende Frage ist: Gibt es in Ihrer Anwendung Orte, wo man alle Arten von Benachrichtigungen gemeinsam prüfen will? Wenn ja, dann ist das ein starkes Zeichen, dass Sie mit STI haften mögen.

Andere Tipps

Haben Sie das Mischmodell Ansatz in Betracht gezogen?

Wenn Sie einzelne Tabelle Vererbung für Ihre Kernbenachrichtigungsfelder verwenden. Dann Offload alle Unikate auf bestimmte Tabellen / Modelle in ein gehört zu / hat eine Beziehung zu Ihrer Benachrichtigung Subklassen.

Es ist ein wenig mehr Aufwand einzurichten, aber klappt ziemlich trocken sein, wenn alle Klassen und Tabellen definiert. Es scheint wie eine ziemlich effiziente Art, die Dinge zu speichern. Mit eifrigen Laden sollten Sie nicht verursachen zu viel zusätzliche Belastung für die Datenbank.

Für die Zwecke dieses Beispiels lässt vermuten, dass E-Mails keine eindeutigen Details haben. Hier ist, wie es abbildet.

class Notification < ActiveRecord::Base
  # common methods/validations/associations
  ...

  def self.relate_to_details
    class_eval <<-EOF
      has_one :details, :class_name => "#{self.name}Detail"
      accepts_nested_attributes_for :details
      default_scope -> { includes(:details) }
    EOF
  end
end

class SMS < Notification
  relate_to_details

  # sms specific methods
  ...
end

class Twitter < Notification
  relate_to_details

  # twitter specific methods
  ...
end

class Email < Notification

  # email specific methods
  ...
end

class SMSDetail < ActiveRecord::Base
  belongs_to :SMS, :class_name => "SMS"           

  # sms specific validations
  ...
end

class TwiterDetail < ActiveRecord::Base
  belongs_to :twitter

  # twitter specific validations
  ...
end

Jeder der Detailtabellen wird eine Benachrichtigungs-ID und nur Spalten, die Form der Kommunikation Bedürfnisse enthalten, die nicht in der Tabelle Benachrichtigungen enthalten ist. Obwohl es wäre ein zusätzlichen Methodenaufruf bedeutet medienspezifische Informationen zu erhalten.

  

Das ist gut zu wissen, aber denken Sie, es ist notwendig?

Nur sehr wenige Dinge notwendig sind, um in Bezug auf Design. Als CPU und Speicherplatz Rückgang der Kosten zu tun, um diese notwendigen Design-Konzepte. Ich schlug vor, diese Regelung, weil es das Beste aus beiden STI und MTI bietet und entfernt einige ihrer Schwächen.

Was Vorteile gehen:

Dieses Schema stellt die Konsistenz der STI. Mit Tabellen, die nicht brauchen neu erstellt werden. Die verknüpfte Tabelle wird um Dutzende von Spalten in dem in 75% der Zeilen leer sind. Sie erhalten auch die einfache Unterklasse Schöpfung. Wo Sie benötigen nur eine passende Tabelle Details, wenn Ihr neuer Typ nicht vollständig durch die Grundbenachrichtigungsfelder abgedeckt zu erstellen. Es hält auch alle Benachrichtigungen einfach iterieren.

Von MTI erhalten Sie die Speichereinsparungen und die einfache Anpassung bei der Erfüllung einer Bedarfsklasse, ohne dass die gleichen Spalten für jede neue Meldungsart neu zu definieren. Nur die Einzigen.

Doch diese Regelung führt auch über die großen Fehler mit STI. Die Tabelle wird 4. ersetzen, die verursacht Verlangsamung beginnen kann, sobald es riesig wird.

Die kurze Antwort ist, nicht dieser Ansatz nicht notwendig ist. Ich sehe es als der DRY Weg, das Problem effizient zu handhaben. In dem sehr kurzen Laufe STI ist der Weg, es zu tun. Auf sehr lange Sicht ist MTI der Weg zu gehen, aber wir reden über den Punkt, wo man Millionen von Meldungen getroffen. Dieser Ansatz ist ein paar nette Mittelweg, die leicht erweiterbar ist.

Detaillierte gem

ich ein Juwel über Ihre Lösung aufgebaut haben: https://github.com/czaks/detailed. Mit ihm können Sie Ihre Mitteilung Klasse vereinfachen:

class Notification < ActiveRecord::Base
  include Detailed
end

Der Rest geht die bisherige Art und Weise.

Als zusätzlichen Bonus können Sie nun Zugriff (Lesen, Schreiben, beziehen) die Unterklasse spezifische Attribute direkt: notification.phone_number, ohne auf: notification.details.phone_number. Sie können auch die gesamten Code in den wichtigsten Klassen und Unterklassen schreiben, leer auf das Detail-Modell zu verlassen. Sie werden weniger Anfragen auch (im obigen Beispiel 4 anstelle von N + 1) in der Lage zu tun, auf große Datensätze Notification.all_with_details statt dem regulären Notification.all verwendet wird.

Bitte beachten Sie, dass die aktuelle Zeit an dieses Juwel nicht sehr gut getestet, obwohl es in meinem usecase funktioniert.

Ich weiß, das alt ist, aber mit einer Lösung zu kommen Ich sehe mögliche Antworten, nachdem die sie überall benutzen könnten! Ich gegabelt vor kurzem ein vielversprechendes Projekt mehr Tabellen Vererbung und Klassenvererbung in Rails zu implementieren. Ich habe ein paar Tage verbrachte es zu einer schnellen Entwicklung, Fehlerbehebungen unterworfen wird, zu kommentieren und Dokumentation und haben es als CITIER Klassenvererbung und Tabelle Vererbung Einbettungen für Rails wieder freigegeben wird.

ich denke, es sollte Ihnen erlauben, zu tun, was Sie, indem Sie einfach die Konstruktion der Modelle benötigt, wo Twitter, E-Mail und SMS von Benachrichtigung erben. Dann haben die Migration für Benachrichtigungen nur enthalten gemeinsame Attribute, und die, die für die drei Subtypen umfassen ihre einzigartigen Eigenschaften.

oder sogar eine Funktion in der Root-Mitteilung Klasse definieren und überlastet es in Subklassen etwas anderes zurück.

Betrachten Sie es sehen geben: https://github.com/PeterHamilton/citier

Ich finde es so nützlich! Ich würde (übrigens) begrüßen jede Hilfe für die Gemeinschaft in Fragen und Tests, Code Bereinigung etc! Ich weiß, das ist etwas, was viele Menschen würden zu schätzen wissen.

Bitte stellen Sie sicher, dass Sie regelmäßig aktualisieren jedoch, weil, wie ich sagte, es hat sich verbessert / von Tag zu Tag entwickelt sich weiter.

has_one :details, :class_name => "#{self.class.name}Detail"

funktioniert nicht. self.class.name im Rahmen einer Klassendefinition ist ‚Klasse‘ so: class_name ist immer ‚ClassDetail‘

So muss es sein:

has_one :details, :class_name => "#{self.name}Detail"

Aber sehr schöne Idee!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top