Skip to content
Lance Pollard edited this page Apr 12, 2012 · 1 revision

One-to-One Relationships

One to one relationships where the children are referenced in the parent document are defined using Tower's has_one and belongs_to macros.

Defining

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.

Storage

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

Accessors

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

Build and Create

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

Polymorphic behavior

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

Dependent Behavior

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.

Tower.js

Everything here will be reflected on http://towerjs.org/guides.

Clone this wiki locally