We have seen how we can configure an author with following
and followers
using the inverse_of
option. Now, let's build the Author
and his followers using cyclic relationships! This can be done as follows:
class Author include Mongoid::Document embeds_many :child_authors, class_name: "Author", cyclic: true embedded_in :parent_author, class_name: "Author", cyclic: true end
And let's update the objects as follows:
irb> a = Author.first
=> #<Author _id: 4e86e4b6fed0eb0be0000011, _type: nil, name: "Charles Dickens">
irb> a.child_authors << Author.last
=> true
irb> a.child_authors.first.parent_author
=> #<Author _id: 4ef5ab6ffed0eb89bf000001, _type: nil, name: "Mark Twain">
We now embed an array called child_authors
into the Author
document and reference the parent using the parent_author
field.
We can also do the exact same thing we just saw using the following code:
class author include Mongoid::Document recursively_embeds_many end
This is a method to embed documents. It takes these additional options including the already explained :as, :cascade_callbacks, :cyclic
, and :order
.
This method tells us which object this is embedded in. It's very important that this be configured when we are setting up the embedded relations.
class Review include Mongoid::Document embedded_in :book end
This tells Mongoid that the review document is embedded inside the book.
As we must set the embedded_in
relation between the parent and the child, how do we embed the same document in different objects? Make it polymorphic! We have seen some examples of how to write polymorphic relations for embedded objects in the previous chapter. Go for it!
What if we want to save the relation twice in the same parent class? For example, in the Vehicle
model, we want the source and the destination fields but both are Location
objects. The name
option specifies in which field the information would be stored. Have a look at the following code:
class Vehicle include Mongoid::Document embeds_one :source, class_name: "Location" embeds_one :destination, class_name: "Location" end class Location include Mongoid::Document embedded_in :vehicle, name: :source embedded_in :vehicle, name: :destination end
Let's see how this would work. Execute the following code:
irb> v = Vehicle.first
=> #<Vehicle _id: 4f042dd0fed0ebc4c5000001, _type: "Vehicle">
irb> v.source = Location.new
=> #<Location _id: 4f214bf7fed0eb863b000001, _type: nil>
irb> v.destination = Location.new
=> #<Location _id: 4f214bfcfed0eb863b000002, _type: nil>
This is how we can embed the same object into the document under different names using the :name
option just explained.
18.216.4.176