Skip to content

Instantly share code, notes, and snippets.

@cblavier
Last active April 8, 2017 14:30
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save cblavier/7889042 to your computer and use it in GitHub Desktop.
Save cblavier/7889042 to your computer and use it in GitHub Desktop.
Helps to override find method for a Mongoid embedded document.
module Mongoid
# Helps to override find method in an embedded document.
# Usage :
# - add to your model "include Mongoid::EmbeddedFindable"
# - override find method with:
# def self.find(id)
# find_through(Book, 'chapter', id)
# end
module EmbeddedFindable
extend ActiveSupport::Concern
included do
# Search an embedded document by id.
#
# Document is stored within embedding_class collection, and can be accessed through provided relation.
# Also supports chained relationships (if the searched document is nested in several embedded documents)
#
# Example, with a chapter embedded in a book, the book being embedded in a library.
# use find_through(Library, "books", book_id) in Book class
# and find_through(Library, "books.chapters", chapter_id) in Chapter class
def self.find_through(embedding_class, relation, id = nil)
return nil if id.nil? || id.blank?
id = Moped::BSON::ObjectId.from_string(id) if id.is_a?(String)
relation = relation.to_s unless relation.is_a?(String)
relation_parts = relation.split('.')
parent = embedding_class.send(:all)
while relation_parts.length > 0
item = if parent.is_a?(Mongoid::Criteria) || parent.is_a?(Array)
parent.where("#{relation_parts.join('.')}._id" => id).first
else
parent
end
return nil if item.nil?
parent = item.send(relation_parts.shift)
end
if parent.is_a?(Mongoid::Criteria) || parent.is_a?(Array)
parent.where('_id' => id).first
else
parent
end
end
end
end
end
@rdetert
Copy link

rdetert commented Nov 3, 2014

Thanks, works great.

@Startouf
Copy link

Startouf commented Apr 8, 2017

Hey did you suggest the mongoid developers to add this ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment