所以,以为我昨晚有这个工作,可以发誓。现在它没有工作,我想是时候寻求帮助了。
我在数据库中定义动态字段,半 EAV 风格,现在让我们说一下,我不想听听你对 EAV 是否是个好主意的意见:)
无论如何,我所做的与我过去所做的有点不同,基本上当添加一个属性(或字段)时,我创建一个添加列到特定属性表迁移并运行它(或删除它)——无论如何,因为中间有一个类别层,它是定义所有属性的直接关系,所以我不能使用实际的属性名称作为列名,因为属性是特定于类别的。
所以,如果它可以帮助你形象化
Entity
belongs_to :category
Category
has_many :entities
EntityAttribute
belongs_to :category
EntityAttributeValue
belongs_to :entity_attribute
belongs_to :entity
随着新属性的创建,EAV 表水平跨越,列标记为属性_1 属性_2,其中包含该特定实体的值。
无论如何——我试图在实体模型上使方法动态化,所以我可以调用@entity.actual_attribute_name,而不是@entity.entity_attribute_value.field_5
这是我认为有效的代码 -
def method_missing(method, *args)
return if self.project_category.blank?
puts "Sorry, I don't have #{method}, let me try to find a dynamic one."
puts "let me try to find a dynamic one"
keys = self.project_category.dynamic_fields.collect {|o| o.name.to_sym }
if keys.include?(method)
field = self.project_category.dynamic_fields.select { |field| field.name.to_sym == method.to_sym && field.project_category.id == self.project_category.id }.first
fields = self.project_category.dynamic_field_values.select {|field| field.name.to_sym == method }
self.project_category_field_value.send("field_#{field.id}".to_sym, *args)
end
end
然后今天当我回到代码时,我意识到虽然我可以在 rails 控制台中设置属性,并且它会返回正确的字段,但当我保存记录时,EntityAttributeValue 没有被更新(表示为 self.project_category_field_value,上面。 )
所以在进一步研究之后,看起来我只需要添加一个 before_update 或 before_save 回调来手动保存属性,这就是我注意到的地方,在回调中,它会重新运行 method_missing 回调,就好像对象被复制一样(并且新对象是原始对象的副本),或者什么,我不太确定。但是在保存过程中或之前的某个时刻,我的属性消失了。
所以,好吧,我想我在输入后回答了我自己的问题,我需要设置一个实例变量并检查它是否存在于我的 method_missing 方法的开头(对吗?)也许这不是发生了什么我不知道,但我也问是否有更好的方法来做我想做的事情。
如果使用 method_missing 是一个坏主意,请解释原因,因为在浏览有关方法缺失的帖子时,我听到一些人抨击它,但没有一个人愿意提供一个合理的解释来解释为什么方法缺失是一个糟糕的解决方案。
提前致谢。