Time for action — setting up cyclic relations

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">

What just happened?

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

Options for embeds_many

This is a method to embed documents. It takes these additional options including the already explained :as, :cascade_callbacks, :cyclic, and :order.

:versioned option

We can version different embedded documents. This should not be used directly but via the versioning module. This automatically embeds versions as an embedded document array in the document. We shall learn about this later in the chapter.

Options for embedded_in

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.

Tip

Without embedded_in method in the model, the document would not get embedded at all!

class Review
include Mongoid::Document
embedded_in :book
end

This tells Mongoid that the review document is embedded inside the book.

Have a go hero — embedded polymorphic relations

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!

:name option

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.4.176