[英]Rails model attributes that are sometimes virtual and sometimes real
我有一个非常复杂的Rails(v 3.2)模型,正在对多个表进行手动选择。 这对于获取显示模型所需的所有数据非常有用。 但是,当我的数据不存在并且必须创建一个虚拟对象时,这些列在我的模型中就不存在。 对于我的一生,我想不出一种方法来支持模型上的虚拟列和实际列。
比这复杂得多,但这是我目前拥有的一般选择:
class MyObject < ActiveRecord::Base
attr_accessible :apples, :bananas, :oranges
def self.get(id)
select("my_objects.*, table1.apples, table2.bananas, table3.oranges")
.joins("left outer join table1 on something
left outer join table2 on something
left outer join table2 on something")
.where(:my_object => id)
end
end
当id
存在时,此功能非常适合我需要显示的内容。 但是,在某些情况下, id
不存在,因此我必须显示一个虚拟(或默认)对象。
我以为我可以为该虚拟对象做这样的事情:
@my_object = MyObject.new({:apples => 1,
:bananas => 50,
:oranges => 10})
但是当然,在视图中,当我执行@my_object.apples
,会出现错误,因为MyObject实际上没有这些列:
ActionView::Template::Error (unknown attribute: apples)
我下一步是将attr_accessor
添加到MyObject
模型:
attr_accessor :apples, :bananas, :oranges
这对于MyObject
的virtual
版本非常理想。 但是现在,当试图显示对象的真实版本时,我所有的苹果,香蕉和橙子都为零! 我认为这是因为attr_accessor
getter和setter覆盖了select返回的内容。
如何在此模型上同时支持虚拟属性和实际属性?
ps我尝试了多种使用method_missing
和define_method
,但是一直无法获得成功的东西。
有趣的问题。
一种方法是像这样为虚拟属性定义setter方法
# MyObject.rb
def set_virtual_attribs=(hsh)
hsh.map{|key,value| self[key] = value}
end
然后可以像这样创建一个虚拟对象
@my_object = MyObject.new(:set_virtual_attribs => {
:apples => 1,
:bananas => 50,
:oranges => 10
})
现在,虚拟属性应以@my_object.apples
形式提供,并且除非调用set_virtual_attribs
否则它不会覆盖任何实际对象的属性方法。
我建议研究一下Null对象模式 ; 我认为这些思路对您的情况会有所帮助。
通常的想法是,创建一个可以代替原始对象的对象,而不用在各处进行nil检查,并使用一些合理的默认值。
我假设class MyObject
定义之外的内容决定了何时id
不存在,因此您需要进行@my_object = MyObject.new({:apples => 1,...
调用。而不是创建实例。在MyObject
那里,您可以拥有一个不同的类,例如:
class MyNilObject
def apples
1
end
def bananas
50
end
def oranges
10
end
end
然后执行@my_object = MyNilObject.new
。 如果要求您能够动态设置这些默认值,则可以有一个带有哈希值,分配属性并具有attr_readers的def initialize
。
此类将是一个普通的旧Ruby对象,它将没有任何数据库持久性。 它需要实现您的视图在MyObject
实例上调用的任何其他方法。
我不确定在渲染对象后在这种情况下要做什么,因此您可能需要在该对象上实现诸如create
的方法,该方法会将其转换为MyObject
的实例并将其潜在地保存在数据库中。
您可以覆盖模型中的访问器方法:
class MyObject < ActiveRecord::Base
def apples
read_attribute(:apples) || 1
end
# etc ....
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.