Я хочу отправить PR, чтобы добавить метод get_like в PluginStore.
get_like будет извлекать все записи для указанного плагина, ключи которых начинаются с одного и того же слова.
Пример использования
Если плагин имеет две или более сущностей, которые он хочет хранить, например, яблоки и апельсины, он будет сохранять данные как apple_1, apple_2… и orange_1, orange_2 от плагина с именем fruits.
Чтобы извлечь все апельсины, можно просто вызвать PluginStore.get_like(‘fruits’, ‘orange’) и т.д.
Что думает команда и разработчики плагинов об этом?
Я лично не сталкивался с необходимостью использовать этот паттерн. Вы видели его в публичных плагинах или только в том, который вы создаёте?
К тому же, это не так уж и долго вводить:
PluginStoreRow.where("plugin_name = 'fruits' AND key LIKE 'orange%')
Если вы часто используете такие запросы, я бы рекомендовал добавить в ваш плагин вспомогательную функцию или класс. Также не забудьте убедиться, что для этих запросов созданы соответствующие индексы.
Я работал над этой функцией для плагина custom-wizards и хотел получить всех волшебников.
Ключ, используемый для этого, представляет собой строку, уникальную для каждого волшебника. Этот случай обрабатывался путем получения всех строк для плагина и их фильтрации по полю value, что приемлемо для небольшого количества записей, но не является оптимальным для большого плагина. Похоже, что таблица plugin_store_rows предназначена для хранения данных, похожих на настройки плагина.
Лично я считаю, что это могло бы открыть возможность хранения в таблице plugin_store_rows данных, не являющихся настройками.
В целом я рекомендую создавать собственные таблицы через миграции, если PluginStoreRow нельзя запрашивать нужным вам образом. Это сейчас часто делается в нескольких плагинах и отлично работает!
Однако он все еще используется в некоторых местах, включая саму основную кодовую базу Discourse, например, в модели Reviewables.
Я также использую этот паттерн в ряде плагинов.
Основная причина использования этого паттерна заключается в том, что таблица plugin_store_rows используется несколькими плагинами (а также некоторыми основными службами), поэтому идентифицирующие столбцы, то есть id и plugin_name, не могут использоваться для внутренней идентификации в каждой системе, использующей PluginStore. Вместо этого в столбце key используется строковая система.
Что касается изменения структуры базы данных изнутри плагина, у @gdpelican есть хороший пост на эту тему:
Лично я все еще довольно осторожен в этом вопросе, так как при работе с сторонним плагином вы не контролируете пространство имен, удаление вашего плагина и потенциально конфликтующие изменения, вносимые в основную кодовую базу Discourse.
Как упоминает @gdpelican, вам необходимо предоставить способ для пользователя плагина удалить изменения в базе данных, если он удалит плагин.
Предоставьте метод для пользователей, чтобы очистить ваши изменения в базе данных, если они больше не хотят ваш плагин. Я сделал это с помощью задачи rake.
Мне кажется, это слишком подробно для большинства пользователей плагинов и создает риск, если они не осведомлены об этой детали.
Более того, я пока не нашел реальной необходимости выходить за рамки PluginStore и CustomFields.
Тем не менее, лично я был бы за появление нового метода по этому образцу в PluginStore, так как считаю этот паттерн полезным.
@david, мне было бы интересно узнать ваше мнение по вышеизложенному.
Как уже сказал @eviltrout, мы сейчас успешно используем миграции и выделенные таблицы в ряде плагинов. Возможность применять ограничения на уровне базы данных помогла повысить производительность (поиск по любому столбцу) и целостность данных (благодаря уникальным индексам). Эти два аспекта оказались особенно важны для масштабов некоторых наших хостинговых клиентов — о таком я раньше, до вступления в команду, даже не задумывался.
Первым значимым плагином, над которым я работал, был chat-integration. В нём я реализовал довольно сложный «фейковый ActiveRecord», опирающийся на хранилище плагинов. Сейчас, оглядываясь назад, понимаю, что выделенные таблицы были бы гораздо лучшим выбором, и, возможно, в будущем я рассмотрю возможность миграции этого плагина на такую архитектуру.
Я согласен, когда речь идёт об изменении основных таблиц. Добавление или изменение столбцов в существующих таблицах может иметь непредвиденные последствия в будущем, и эти изменения останутся даже после удаления плагина. Я настоятельно не рекомендую так делать.
Выделенные же таблицы сопряжены с относительно низким риском. Если плагин будет удалён, эти таблицы просто останутся в базе, не вызывая никаких негативных побочных эффектов (при условии, что вы не создадите ограничения внешних ключей). Оставление данных в базе «не хуже», чем использование хранилища плагинов.
Что касается очистки, мы могли бы рассмотреть возможность предоставления задач Rake, которые «отменяли» бы миграции плагинов для удаления данных. Но честно говоря, я не думаю, что это будет востребовано. Я исхожу из того, что люди редко удаляют плагины, а если и удаляют, то предпочитают оставить данные на случай повторной установки плагина.
Как автор этого кода, я, возможно, должен немного прояснить ситуацию. Идентификаторы приоритетов являются константами, а не реляционными данными. Я категорически не рекомендую использовать something_id, если идентификаторы неизвестны заранее. В данном случае каждый приоритет рассматривается как синглтон, и я посчитал, что любая таблица, которую я бы создал, фактически стала бы клоном PluginStore!