Je souhaite soumettre une PR pour ajouter une méthode get_like à PluginStore.
get_like récupérera tous les enregistrements pour un plugin donné, dont la clé commence par le même mot.
Cas d’utilisation
Si un plugin doit stocker deux entités ou plus, par exemple des pommes et des oranges, il stockera les données sous forme de apple_1, apple_2… et orange_1, orange_2 depuis un plugin nommé fruits.
Pour récupérer toutes les « oranges », il suffit d’appeler PluginStore.get_like(‘fruits’, ‘orange’), etc.
Qu’en pensent l’équipe et les développeurs de plugins ?
Je ne pense pas avoir personnellement eu besoin de ce motif. L’avez-vous vu dans des plugins publics, ou seulement dans celui que vous créez ?
De plus, ce n’est pas trop long à taper :
PluginStoreRow.where("plugin_name = 'fruits' AND key LIKE 'orange%')
Je vous recommande d’ajouter une fonction ou une classe d’aide à votre plugin si vous le faites souvent. Assurez-vous également de disposer des index appropriés pour ces requêtes.
Je travaillais sur cette fonctionnalité pour le plugin custom-wizards et je voulais récupérer tous les sorciers.
La clé utilisée est une chaîne de caractères unique pour chaque sorcier. Ce cas était géré en récupérant toutes les lignes pour le plugin et en les filtrant en fonction de la valeur, ce qui convient pour un petit nombre d’enregistrements mais n’est pas idéal pour un gros plugin. Il semble que plugin_store_rows soit destiné à stocker des données de type paramètres pour le plugin.
Je pense personnellement que cela ouvrirait la possibilité de stocker des données de type non-paramètres dans la table plugin_store_rows.
En général, je recommande de créer vos propres tables via des migrations si PluginStoreRow ne peut pas être interrogé comme vous le souhaitez. Cela est désormais couramment fait dans plusieurs plugins et fonctionne très bien !
Le modèle consiste à utiliser le champ key dans la table plugin_store_rows pour stocker à la fois un espace de noms et un identifiant unique, c’est-à-dire :
<namespace>_<id>
Ce modèle est moins courant dans les plugins principaux de Discourse ces derniers jours, avec un déclin général de l’utilisation de PluginStore, par exemple :
Cependant, il est toujours utilisé à certains endroits, y compris dans le code source principal de Discourse lui-même, par exemple dans le modèle Reviewables.
J’utilise également ce modèle dans plusieurs plugins.
La raison principale de l’utilisation de ce modèle est que la table plugin_store_rows est utilisée par plusieurs plugins (et certains services principaux), de sorte que les colonnes d’identification, c’est-à-dire id et plugin_name, ne peuvent pas être utilisées pour l’identification interne dans chaque système utilisant PluginStore. Un système basé sur des chaînes de caractères est donc utilisé dans la colonne key.
En ce qui concerne la modification de la structure de la base de données depuis un plugin, @gdpelican a un excellent post à ce sujet :
Personnellement, je suis encore très prudent à ce sujet car travailler sur un plugin tiers sur lequel vous n’avez aucun contrôle en matière d’espace de noms, de suppression de votre plugin et de modifications potentiellement conflictuelles apportées à Discourse principal comporte des risques.
Comme le mentionne @gdpelican, vous devez prévoir un moyen pour vos utilisateurs de plugin de supprimer les modifications de la base de données s’ils désinstallent le plugin.
Prévoyez une méthode pour que les utilisateurs nettoient vos modifications de base de données s’ils ne veulent plus de votre plugin. Je l’ai fait avec une tâche rake.
Je pense que c’est trop technique pour la plupart des utilisateurs de plugins et présente un risque s’ils ne sont pas conscients de ce détail.
De plus, je n’ai pas encore trouvé de véritable besoin de sortir des limites de PluginStore et CustomFields.
Tout cela dit, personnellement, je serais en faveur d’une nouvelle méthode dans ce sens dans PluginStore, car je trouve ce modèle utile.
@david, je serais intéressé par vos réflexions sur ce qui précède également.
Comme l’a dit @eviltrout, nous utilisons désormais des migrations et des tables dédiées dans plusieurs plugins, avec un grand succès. La possibilité d’imposer des contraintes de base de données a permis d’améliorer les performances (recherches dans n’importe quelle colonne) et l’intégrité des données (grâce aux index uniques). Ces deux aspects se sont révélés particulièrement importants à l’échelle de certains de nos clients hébergés – ce n’est pas vraiment quelque chose que j’avais envisagé avant de rejoindre l’équipe.
Le premier plugin substantiel sur lequel j’ai travaillé était chat-integration, et j’y ai implémenté un très fastidieux « faux activerecord », qui s’appuie sur le magasin de plugins. En y repensant, des tables dédiées auraient été un choix bien meilleur, et je pourrais envisager de migrer ce plugin vers cette approche à l’avenir.
Je serais d’accord, lorsqu’il s’agit de modifier les tables principales. Ajouter ou modifier des colonnes sur des tables existantes pourrait avoir des conséquences imprévues plus tard, et ces modifications subsisteront même si le plugin est désinstallé. Je déconseille vivement de le faire.
Les tables dédiées, en revanche, présentent un risque relativement faible. Si le plugin est désinstallé, elles resteront simplement en place, sans aucun effet secondaire négatif (à condition de ne pas introduire de contraintes de clé étrangère). Laisser des données en suspens n’est « pas pire » que d’utiliser le magasin de plugins.
En ce qui concerne le nettoyage, nous pourrions envisager de fournir des tâches rake qui « inversent » les migrations de plugins pour effectuer le nettoyage. Mais pour être honnête, je ne pense pas que cela sera beaucoup utilisé. Mon hypothèse est que les gens désinstallent rarement les plugins, et lorsqu’ils le font, ils préfèrent conserver les données au cas où ils souhaiteraient les réinstaller plus tard.
En tant qu’auteur de ce code, je devrais peut-être clarifier un peu les choses. Les identifiants de priorité sont des constantes et non des données relationnelles. Je déconseillerais absolument d’utiliser something_id lorsque les identifiants ne sont pas connus à l’avance. Dans ce cas, chaque priorité est considérée comme un singleton, et j’ai estimé que n’importe quelle table que je créerais serait essentiellement un clone du PluginStore de toute façon !