fzngagan
(Faizaan Gagan)
1
我想提交一个 PR,为 PluginStore 添加一个 get_like 方法。
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%')
如果你经常需要这样操作,建议为你的插件添加一个辅助函数或类。同时,请确保已为这些查询配置了合适的索引。
fzngagan
(Faizaan Gagan)
3
我正在为 custom-wizards 插件开发这个功能,想要获取所有巫师。使用的键是一个字符串,每个巫师都是唯一的。目前的处理方式是为插件获取所有行,然后根据 value 进行过滤。这对于少量记录来说没问题,但对于大型插件来说并不理想。看起来 plugin_store_rows 是用于存储插件的“类设置”数据的。
我个人认为,这可能会引出在 plugin_store_rows 表中存储“非设置类”数据的想法。
(如果听起来有些奇怪,请见谅)
通常情况下,如果无法按所需方式查询 PluginStoreRow,我建议您通过迁移创建自己的表。这目前在多个插件中已广泛采用,效果非常好!
angus
(Angus McLeod)
6
通常的做法是在 plugin_store_rows 表的 key 字段中同时存储命名空间和唯一标识符,即:
<namespace>_<id>
如今,在核心 Discourse 插件中,这种模式的使用频率有所下降,PluginStore 的整体使用率也在降低,例如:
不过,该模式仍被用于某些地方,包括核心 Discourse 代码库本身,例如 在 Reviewables 模型中。
我自己在多个插件中也使用了这种模式。
使用该模式的主要原因是,plugin_store_rows 表被多个插件(以及一些核心服务)共用,因此标识列(即 id 和 plugin_name)无法用于各个使用 PluginStore 的系统内部的识别。因此,key 列改用基于字符串的系统。
关于在插件内部更改数据库结构,@gdpelican 有一篇很好的帖子:
就我个人而言,我对这样做仍相当谨慎,因为作为第三方插件,你无法控制命名空间、无法控制插件是否会被移除,也无法控制核心 Discourse 可能做出的潜在冲突性更改。
正如 @gdpelican 提到的,你需要提供一种方式,让用户在卸载插件时能够清理数据库的更改。
为用户提供一种方法,以便在不再需要你的插件时清理你的数据库更改。我通过一个 rake 任务实现了这一点。
我觉得这对大多数插件用户来说过于琐碎,如果他们不了解这一细节,还存在风险。
此外,我尚未发现有必要超出 PluginStore 和 CustomFields 的范围。
话虽如此,就我个人而言,我支持在 PluginStore 中添加类似的新方法,因为我认为这种模式很有用。
@david,也想听听你对上述内容的看法。
david
(David Taylor)
7
正如 @eviltrout 所说,我们现在在许多插件中使用了迁移和专用表,并取得了巨大成功。能够强制实施数据库约束有助于提升性能(任意列的查找)和数据完整性(通过唯一索引)。这两点在我们部分托管客户的规模下显得尤为重要——这在我加入团队之前并未充分考虑。
我参与开发的第一款实质性插件是 chat-integration,当时我实现了一个非常繁琐的“模拟 ActiveRecord”,它依赖于插件存储。 hindsight 来看,使用专用表会是更好的选择,未来我可能会考虑将该插件迁移到这种模式。
我同意,当涉及修改核心表时,在现有表上添加或修改列可能会在日后产生意想不到的后果,并且即使插件被卸载,这些更改也会保留。我强烈不建议这样做。
另一方面,专用表的风险相对较低。如果插件被卸载,这些表只会保留下来,而不会产生任何负面影响(只要你不引入任何外键约束)。留下数据并不比使用插件存储更糟糕。
关于清理工作,我们可以考虑提供用于“逆向”插件迁移的 rake 任务来进行清理。但说实话,我认为这不会得到太多使用。我的假设是,人们很少卸载插件,即使卸载了,他们也更倾向于保留数据,以防将来需要重新安装。
作为该代码的作者,我或许应该稍作澄清。优先级 ID 是常量,而非关系数据。如果 ID 无法预先确定,我绝对不建议使用 something_id。在这种情况下,每个优先级都被视为单例,而且我认为,无论我创建什么样的表,本质上都会是 PluginStore 的克隆!