-
Notifications
You must be signed in to change notification settings - Fork 0
One to one relationships where the children are referenced in the parent document are defined using Tower's has_one
and belongs_to
macros.
The parent document of the relation should use the has_one macro to indicate is has 1 referenced child, where the document that is referenced in it uses belongs_to
.
class Person extends Tower.Model
@hasOne "game"
class Game
include Tower::Document
field :name, type: String
belongs_to :person
Definitions are required on both sides to the relation in order for it to work properly.
When defining a relation of this nature, each document is stored in it's respective collection, but the child document contains a "foreign key" reference to the parent.
# The parent person document.
{ "_id" : ObjectId("4d3ed089fb60ab534684b7e9") }
# The child post document.
{
"_id" : ObjectId("4d3ed089fb60ab534684b7f1"),
"person_id" : ObjectId("4d3ed089fb60ab534684b7e9")
}
Accessing the relations is handled through the methods created based on the names of the relations. The following example shows basic access on both sides of the relation.
# Return the child game.
person.game
# Set the child game.
person.game = [ Game.new ]
# Return the parent person.
game.person
# Set the parent person.
game.person = Person.new
From the parent side, documents in the referenced child can be initialized or created using the specially defined methods.
# Create a new child game given the provided attributes.
person.build_game(name: "Tron")
# Create a persisted child game.
person.create_game(name: "Tron")
# Replace the parent with a new one from the attributes.
game.build_person(title: "Prince")
# Replace the parent with a newly saved one from the attributes.
game.create_person(title: "Prince")
=== Removal
Documents in the referenced many can be removed by either calling delete on the child or setting it to nil.
# Delete the child document
person.game.delete
person.game.destroy
person.game = nil
When a child referenced document can belong to more than one type of parent document, you can tell Tower to support this by adding the as option to the definition on the parents, and the polymorphic option on the child.
class Arcade
include Tower::Document
has_one :game, as: :playable
end
class Person
include Tower::Document
has_one :game, as: :playable
end
class Game
include Tower::Document
belongs_to :playable, polymorphic: true
end
You can tell Tower what to do with child relations of a has one when unsetting the relation via the dependent option. The valid options are:
-
:delete
Delete the child document. -
:destroy
Destroy the child document. -
:nullify
Orphan the child document.
Polymorphic example illustrating different kinds of dependency behavior:
class Person
include Tower::Document
has_one :game, as: :playable, dependent: :delete
end
class Arcade
include Tower::Document
has_one :game, as: :playable, dependent: :nullify
end
# Deletes the existing game on the person.
person.game = []
person.game = nil
# Orphans the existing game on the arcade (no delete).
person.game = []
person.game = nil
If the dependent option is not defined, the default is to nullify.