Since the Mongoid API did not make the MongoDB $sample operation visible, I had to manually run a query with the Mongo driver, and I don't know what to do with the results.
I have different classes/collections that adhere to some common interface (I did not want to use inheritance for several reasons), and I am trying to render those as a single collection. I have a code that samples from those three classes
entries = [Class1, Class2, Class3].inject([]) do |array, clazz|
entries << clazz.collection.aggregate([ { '$sample': { size: 10 } } ])
end
This gives me an array of three different Mongo::Collection::View::Aggregation
. I'd like to somehow merge those and be able to instanciate the objects so I can use them in my views (with cells for example)
<%= cell(:profile, collection: entries) %>
Using entries.to_a
will return an array of hashes and not an array of (model) objects. I was hoping it would be the case and that I would then use cells builder to handle the rest of subtle differences between the models
builds do |model, options|
case model
when Class1; Class1Cell
when Class2; Class2Cell
when Class3; Class3Cell
end
EDIT :
I can actually still use to_a
and use the key _type
to find the corresponding Constant/Model. Now the newt question, is how to instanciate a model with the hash, that does not return true
on 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.
The best approach would be to use Mongoid::Document
's class method instantiate
:
Person.instantiate(document)
# or even
Person.instantiate({firstname: 'John', lastname: 'Doe'})
Or for your example:
entries = [Class1, Class2, Class3].inject([]) do |array, clazz|
entries << clazz.collection.aggregate([
{ '$sample': { size: 10 } }
]).map do |document|
clazz.instantiate(document)
end
end
As stated in the description:
Instantiate a new object, only when loaded from the database or when the attributes have already been typecast.
Moreover, it takes selected_fields
as a second parameter which is useful to let it know only the given fields have been loaded from the database.