由于Mongoid API没有使MongoDB $示例操作可见,我不得不手动运行Mongo驱动程序的查询,我不知道如何处理结果。
我有不同的类/集合,它们遵循一些通用接口(我出于几个原因不想使用继承),我试图将它们作为单个集合进行渲染。我有一个从这三个类中抽样的代码
entries = [Class1, Class2, Class3].inject([]) do |array, clazz|
entries << clazz.collection.aggregate([ { '$sample': { size: 10 } } ])
end
这给了我一个由三个不同Mongo::Collection::View::Aggregation
组成的数组。我想以某种方式合并它们并能够实现对象,以便我可以在我的视图中使用它们(例如使用单元格)
<%= cell(:profile, collection: entries) %>
使用entries.to_a
将返回哈希数组,而不是(模型)对象数组。我希望情况会是这样,然后我会使用单元构建器来处理模型之间的其他细微差别
builds do |model, options|
case model
when Class1; Class1Cell
when Class2; Class2Cell
when Class3; Class3Cell
end
编辑:
我实际上仍然可以使用to_a
并使用键_type
来查找相应的常量/模型。现在的问题是,如何使用哈希来实现模型,而不会在true
上返回new_record?
sample = entries.to_a.first
instance = Utility.resolve_class(sample[:_type]).new(entry_hash)
# Problem is...
instance.new_record? # => returns true, but since it comes from the DB it means it has already been persisted so it should return false.
答案 0 :(得分:1)
细胞适用于任何PORO。因此,实现所需内容的最简单方法是创建一个表示模型文件中所需数据的类。只需将其创建为普通的ruby类。您可以隐藏数据查询方法以创建聚合并将一组类作为类方法返回。
类似的东西(你会想要整理一下,这只是一个让你入门的黑客):
# some PORO
class Record
attr_accessor :field_1, :field_2, :field_3
def self.build
# your existing code
entries = [Class1, Class2, Class3].inject([]) do |array, clazz|
entries << profile_collection.collection.aggregate([ { '$sample': { size: 10 } } ])
end
array_of_objects = []
# now for each record within the aggregate create an object
entries.each do |obj|
new_poro = self.new
obj.keys.each do |key|
new_poro.self.instance_variable_set(key, obj[key])
end
array_of_objects.push new_poro
end
return array_of_objects
end
end
# to run it in your controller
@records_in_objects_for_cells = Record.build
# in your views
<%= cell(:record, collection: records_in_objects_for_cells %>
答案 1 :(得分:1)
要回答您编辑的问题,您可以将其设置为false。变量是new_record,如此处所示(http://www.rubydoc.info/github/mongoid/mongoid/Mongoid/Stateful:new_record%3F)。
所以:
r = MongoRecord.find_by(x:y)
e = r.new(e)
e.new_record?
=> true
e.new_record = false
e.new_record?
=> false
MongoId使用此标志来确定它是否持久存在。如果发生持久性事件,它使用_id来知道要更新的记录。
答案 2 :(得分:1)
最好的方法是使用Mongoid::Document
的类方法instantiate
:
Person.instantiate(document)
# or even
Person.instantiate({firstname: 'John', lastname: 'Doe'})
或者例如:
entries = [Class1, Class2, Class3].inject([]) do |array, clazz|
entries << clazz.collection.aggregate([
{ '$sample': { size: 10 } }
]).map do |document|
clazz.instantiate(document)
end
end
如说明中所述:
仅当从数据库中加载或属性已经过类型转换时,才能实例化新对象。
此外,它使用selected_fields
作为第二个参数,这有助于让它知道仅从数据库中加载了给定的字段。