【发布时间】:2019-03-22 16:20:31
【问题描述】:
我正在构建一个应用程序,其中用户是Organisation 的一部分。一个组织有很多Lists,而这些ListItems 又是很多。
现在,我希望管理员用户能够根据他们所属的组织(或者更确切地说,在他们的列表所属的组织上)指定列表项上可用的属性,而无需触及任何代码.
到目前为止,在定义未绑定到数据库中特定列的属性时,我使用了document_serializable,这是一个漂亮的小宝石(基于virtus),它将虚拟属性序列化为数据库中的 JSONB 列.我喜欢这种方法,因为我得到了 virtus 的所有优点(类型、强制、验证等),并且因为数据最终位于 JSONB 列中,这意味着它可以相对轻松地快速加载、索引和搜索.
在动态添加这些用户定义的属性时,我想继续使用这种方法。所以我想做这样的事情:
class ListItem < ApplicationRecord
belongs_to :list
delegate :organisation, to: :list
organisation.list_attributes.each do |a, t|
attribute a, t
end
end
Organisation#list_attributes 返回用户定义的属性名称及其关联类型的散列,例如,可能如下所示:
{
name: String,
age: Integer
}
正如您可能已经猜到的那样,这不起作用,因为organisation.list_attributes.each 实际上是在ListItem 的上下文中运行的,它是Class 的一个实例,而Class 没有#organisation 方法.我希望用一种有意义的方式措辞1。
我尝试过使用after_initialize,但在对象生命周期的那个时刻,#attribute 归ActiveRecord::AttributeMethods::Read 所有,而不是DocumentSerializable::ClassMethods,所以这是一种完全不同的方法,我不知道是否我仍然可以访问我需要的那个,而且它甚至可以工作。
另一种选择是以某种明确的方式找到有问题的组织,Organisation#find-style,但老实说,我不知道应该将必要的信息存储在哪里。
所以,我的问题是:在实例化(初始化或加载2)记录时,有没有办法可以检索存储在其中一个关系的数据库列中的哈希?还是我试图以一种完全被误导的方式构建它,如果是这样,我应该怎么做?
1 澄清一下,如果我像这样直接使用哈希:
class ListItem < ApplicationRecord
belongs_to :list
delegate :organisation, to: :list
{
name: String,
age: Integer
}.each do |a, t|
attribute a, t
end
end
它会起作用,我的问题只是在这个较早的时间点获取记录的关系。
2 我的理解是,每当从数据库创建或加载该类型的记录时,Rails 都会运行模型的代码,这意味着每次发生这种情况时都会重新定义虚拟属性,这就是为什么我我在问如何在这两种情况下做到这一点。
【问题讨论】:
-
请缩小您的问题范围。我需要一些澄清:“初始化或加载列表项时”?你的意思是它们是什么时候创建的?从数据库中选择? “基于位于属于组织的任意数据库列中的数据”任意可能很困难。我想我需要一个例子。
-
@VeridianDynamics 感谢您的评论。我在问题正文中添加了一个示例哈希。我的理解是,如果我的模型主体中有
attribute :name, String,那么每次从数据库创建或加载新实例时都会运行它,所以我需要能够在这两种情况下动态地执行此操作。
标签: ruby-on-rails activerecord virtus