Methode `get_like` zur Klasse PluginStore hinzufügen

Ich möchte einen PR einreichen, um eine Methode get_like zu PluginStore hinzuzufügen.

get_like ruft alle Datensätze für ein bestimmtes Plugin ab, deren Schlüssel mit demselben Wort beginnen.

Gebrauchsfall
Wenn ein Plugin zwei oder mehr Entitäten speichern möchte, sagen wir Äpfel und Orangen, speichert es die Daten als apple_1, apple_2 … und orange_1, orange_2 aus einem Plugin namens fruits.

Um alle Orangen abzurufen, kann man einfach PluginStore.get_like(‘fruits’, ‘orange’) usw. aufrufen.

Was denken das Team und die Plugin-Entwickler dazu?

Ich glaube nicht, dass ich diesen Pattern persönlich je benötigt habe. Hast du ihn in öffentlichen Plugins gesehen oder nur in dem, das du gerade erstellst?

Außerdem ist der Befehl nicht zu lang zu tippen:

PluginStoreRow.where("plugin_name = 'fruits' AND key LIKE 'orange%')

Ich würde empfehlen, eine Hilfsfunktion oder -klasse zu deinem Plugin hinzuzufügen, wenn du das häufiger machst. Stelle außerdem sicher, dass du geeignete Indizes für diese Abfragen hast.

Ich habe an dieser Funktion für das Custom-Wizards-Plugin gearbeitet und wollte alle Zauberer abrufen.
Der verwendete Schlüssel ist eine Zeichenkette, die pro Zauberer eindeutig ist. Dieser Fall wurde durch das Abrufen aller Zeilen für das Plugin und das Filtern basierend auf einem value-Wert gelöst, was für eine kleine Anzahl von Datensätzen in Ordnung ist, aber für ein großes Plugin nicht ideal ist. Es scheint, als sei die Tabelle plugin_store_rows dafür gedacht, plugin-spezifische Daten im Stil von Einstellungen zu speichern.

Ich persönlich denke, dies würde die Idee eröffnen, Daten, die nicht im Stil von Einstellungen sind, in der Tabelle plugin_store_rows zu speichern.

(Vergebt mir, falls es seltsam klingt)

Im Allgemeinen empfehle ich, eigene Tabellen über Migrations zu erstellen, wenn die PluginStoreRow nicht so abgefragt werden kann, wie Sie es möchten. Dies wird mittlerweile in mehreren Plugins üblicherweise so gehandhabt und funktioniert hervorragend!

Oh, das wusste ich nicht. Vielen Dank.

Das Muster besteht darin, das Feld key in der Tabelle plugin_store_rows zu verwenden, um sowohl einen Namespace als auch eine eindeutige Kennung zu speichern, also:

<namespace>_<id>

Dieses Muster wird bei Kern-Discourse-Plugins heutzutage seltener verwendet, da die Nutzung von PluginStore allgemein abnimmt, zum Beispiel:

Es wird jedoch immer noch an einigen Stellen verwendet, einschließlich der Discourse-Kerncodebasis selbst, z. B. im Reviewables-Modell.

Ich verwende das Muster auch in einer Reihe von Plugins.

Der Hauptgrund für die Verwendung dieses Musters ist, dass die Tabelle plugin_store_rows von mehreren Plugins (und einigen Kernservices) genutzt wird. Daher können die identifizierenden Spalten, also id und plugin_name, nicht zur internen Identifizierung innerhalb jedes Systems verwendet werden, das PluginStore nutzt. Stattdessen wird im Feld key ein string-basiertes System verwendet.

Hinsichtlich der Änderung der Datenbankstruktur innerhalb eines Plugins hat @gdpelican einen guten Beitrag dazu verfasst:

Persönlich bin ich immer noch sehr zurückhaltend, dies zu tun, da bei einem Drittanbieter-Plugin, über das man keine Kontrolle hat, Fragen der Namensgebung, ob das Plugin entfernt wird und welche potenziell konfliktträchtigen Änderungen an Discourse-Kernfunktionen vorgenommen werden, bestehen.

Wie @gdpelican erwähnt, müssen Sie eine Möglichkeit bieten, damit Plugin-Benutzer die Datenbankänderungen entfernen können, wenn sie das Plugin deinstallieren.

Bieten Sie eine Methode an, mit der Benutzer Ihre Datenbankänderungen bereinigen können, wenn sie Ihr Plugin nicht mehr benötigen. Ich habe dies mit einem Rake-Task umgesetzt.

Ich finde, das ist für die meisten Plugin-Benutzer zu detailliert und birgt ein Risiko, wenn sie sich dieses Details nicht bewusst sind.

Darüber hinaus habe ich noch keinen echten Bedarf gefunden, über die Grenzen von PluginStore und CustomFields hinauszugehen.

Trotzdem wäre ich persönlich für eine neue Methode in dieser Richtung in PluginStore, da ich das Muster nützlich finde.

@david, ich wäre an deinen Gedanken dazu interessiert.

Wie @eviltrout bereits erwähnt hat, setzen wir in einer Reihe von Plugins mittlerweile erfolgreich auf Migrationen und dedizierte Tabellen. Die Möglichkeit, Datenbank-Constraints durchzusetzen, hat die Leistung (Abfragen in beliebigen Spalten) und die Datenintegrität (durch eindeutige Indizes) verbessert. Diese beiden Aspekte haben sich insbesondere im Maßstab einiger unserer gehosteten Kunden als besonders wichtig erwiesen – etwas, das ich vor meinem Eintritt ins Team kaum bedacht hatte.

Das erste umfangreiche Plugin, an dem ich gearbeitet habe, war chat-integration, und ich habe dort eine sehr umständliche „fiktive ActiveRecord“-Lösung implementiert, die auf dem Plugin-Store aufbaut. Im Nachhinein wären dedizierte Tabellen eine weit bessere Wahl gewesen, und ich werde möglicherweise prüfen, das Plugin in Zukunft dorthin zu migrieren.

Dem stimme ich zu, wenn es um die Modifikation von Core-Tabellen geht. Das Hinzufügen oder Ändern von Spalten in bestehenden Tabellen kann später ungewollte Folgen haben und bleibt auch dann erhalten, wenn das Plugin deinstalliert wird. Davon rate ich dringend ab.

Dedizierte Tabellen sind hingegen mit relativ geringem Risiko verbunden. Wird das Plugin deinstalliert, bleiben sie einfach erhalten, ohne negative Nebeneffekte (sofern Sie keine Fremdschlüssel-Constraints einführen). Zurückgelassene Daten sind „nicht schlimmer“ als die Nutzung des Plugin-Stores.

Im Hinblick auf die Bereinigung könnten wir Rake-Tasks bereitstellen, die Plugin-Migrationen rückgängig machen. Aber ehrlich gesagt glaube ich nicht, dass dies häufig genutzt wird. Meine Annahme ist, dass Leute Plugins selten deinstallieren, und wenn doch, bevorzugen sie es, die Daten zu behalten, falls sie das Plugin später erneut installieren möchten.

Als Autor dieses Codes sollte ich das vielleicht etwas präzisieren. Die Priority-IDs sind Konstanten und keine relationalen Daten. Ich würde dringend davon abraten, something_id zu verwenden, wenn die IDs nicht im Voraus bekannt sind. In diesem Fall wird jede Priorität als Singleton betrachtet, und ich ging davon aus, dass jede von mir erstellte Tabelle im Wesentlichen eine Kopie des PluginStore wäre!