So I created a relationship as such:
Class Business
include MongoMapper::Document
key :published_review_ids , Array , typecast: 'BSON::ObjectId'
many :published_reviews , class: Review , in: :published_review_ids
end
I use the published_review_ids to maintain the sort order of my reviews, this moving them up and down in the array.
So, accessing Business.first.published_review_ids gives me all my ids in the proper order. Accessing Business.first.published_reviews brings me back an array of reviews, but sorted by the default order (generation time).
Is there a way for me to tell this association to always sort based on the order of the array it is based off of?
As a side note, array.first and array.last don't appear to function properly on the returned array of Business.first.published_reviews. Here is a gist that shows some examples of the behavior: https://gist.github.com/09c9a0a23dc67f30a76d
No. The list is unsorted because of how MongoDB works. The query that hits Mongo looks like...
{
"_id": { "$in" => [ObjectId('...'), ObjectId('...'), ObjectId('...')] }
}
...and Mongo's only guarantee is that it will return all the documents that match the query.
If you want to have a default order for your association, you should be able to add it to the declaration.
many :published_reviews, class: Review , in: :published_review_ids, order: :published_at.desc
You could also do this to solve your problem more exactly:
def sorted_published_reviews
published_review_ids.map do |id|
# to_a will only fire a Mongo query the first time through this loop
published_reviews.to_a.find { |review| review.id == id }
end
end
And to your aside:
Calling first and last directly on an association fires queries. Without a sort order, you won't get anything different for them. (see the plucky source)
The following will load the whole association and pull the first/last out of the internal Ruby array:
my_business.published_reviews[0]
my_business.published_reviews[-1]
my_business.published_reviews.to_a.first
my_business.published_reviews.to_a.last
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With