我有一个非常复杂的Rails (v3.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
这对于virtual
版本的MyObject
来说是完美的。但是现在,当我试图展示这个物体的真实版本时,我所有的苹果、香蕉和橘子都是零!我认为这是因为attr_accessor
的getter和setter正在覆盖select返回的内容。
如何在此模型上支持虚拟属性和实际属性?
附注:我尝试过多种使用method_missing
和define_method
的方法,但都无法获得任何成功的东西。
发布于 2013-09-25 14:17:21
有趣的问题。
一种方法是为虚拟attrib定义一个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
,否则不会覆盖实际对象的任何属性方法。
发布于 2013-09-25 15:27:02
我建议研究一下空对象模式;我认为这些思路对您的情况会有帮助。
一般的想法是,与其在任何地方进行零检查,不如创建一个对象,该对象可以代表原始对象,并具有一些合理的默认值。
我假设您的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
。如果您需要能够动态设置这些默认值,那么您可以拥有一个def initialize
,它接受哈希并赋值属性并具有attr_readers。
这个类将是一个没有任何数据库持久性的普通旧Ruby对象。它需要实现视图在MyObject
实例上调用的任何其他方法。
在本例中,我不确定在呈现对象之后要做什么,因此您可能需要在这个对象上实现一个像create
这样的方法,将其转换为MyObject
的一个实例,并可能将其保存在数据库中。
发布于 2013-09-25 15:45:52
您可以重写模型中的访问器方法:
class MyObject < ActiveRecord::Base
def apples
read_attribute(:apples) || 1
end
# etc ....
end
https://stackoverflow.com/questions/19014340
复制