Defining relationships between your ember-data models

When defining model objects in your application, you may realize the need to refer or link two models together, something very similar to what you do in relational databases. Ember Data lets you do that in a very easy manner by providing support for the several possible relationship types that two models can have with each other.

Currently, three types of relationships are supported in ember-data:

  • One-to-one
  • One-to-many
  • Many-to-many

Let's see what each relationship types mean, and how to define it in your model objects.

One-to-one

The one to one type of relationship means that the model attribute is linked to one, and only one, object. In Ember Data, you can link an attribute to one other object by using the DS.belongsTo method. The DS.belongsTo takes in two arguments, the first one in a mandatory argument, specifying the name of the object the attribute links to, and the second argument is an object containing properties to inform the adapter on how to load the object when a response is received from the server. One such property is async. If you set the async property to true, { async: true }, it signals the DS.RESTAdapter (and other types of adapters if they respect this option) that the relationships of this model have to be fetched asynchronously. We will discuss more about loading relationships when we discuss the DS.RESTAdapter.

One example of one to one mapping would be mapping an address type to user type, such as in the following example:

app/models/user.js

import DS from "ember-data";

export default DS.Model.extend({
  name: DS.attr("string"),
  address: DS.belongsTo('address')
});

app/models/address.js

import DS from "ember-data";

export default DS.Model.extend({
  street: DS.attr("string"),
  locality: DS.attr("string"),
  houseNo: DS.attr("number"),
  user: DS.belongsTo('user')
});

The example signifies that there is a direct mapping between a user and an address. A user can have only one address, and an address can have only one user.

One-to-many

The one to many relationship type, as the names suggests, means that a model attribute is of type array, and can have many models of one type linked to that property.

Continuing with our book example, a book can have many reviews linked to it but on the other hand, a review will only belong to one, and only one, book. This can be modeled in ember-data using DS.hasMany() as an attribute type. DS.hasMany like DS.belongsTo can take in two arguments, the first one being a mandatory one, depicting the name of the relationship, and the second one being an optional argument that tells the adapter how to load the relationships of the object.

Let's understand this with the following example:

// File: app/models/book.js
import DS from "ember-data";

export default DS.Model.extend({
  title: DS.attr('string'),
  isbn: DS.attr('string'),
  pages: DS.attr('number'),
  description: DS.attr('string'),
  authors: DS.hasMany('author'),
  publisher: DS.belongsTo('publisher'),
  reviews: DS.hasMany("review")
});

The book model is present at chapter6/example1/app/models/book.js

You can see in the code that a book's attribute reviews are assigned a type of DS.hasMany("reviews"), which means that the book is linked to reviews via has-many relationship type.

Similarly, in order to refer a book back from a review, we will need a DS.belongsTo('book') relationship type defined inside the review class, as follows:

import DS from "ember-data";

export default DS.Model.extend({
  name: DS.attr("string"),
  comment: DS.attr("string"),
  book: DS.belongsTo("book")
});

The review model is present at chapter6/example1/app/models/review.js

Many-to-many

A many-to-many relationship type is the one in which one object can have an attribute that links to zero or more instances of another object, and vice versa. For example, a book can have many authors linked to it, and an author can write one or more books. Let's make this clearer by using an example:

// File: app/models/book.js
import DS from "ember-data";

export default DS.Model.extend({
  title: DS.attr('string'),
  isbn: DS.attr('string'),
  pages: DS.attr('number'),
  description: DS.attr('string'),
authors: DS.hasMany('author'),
  publisher: DS.belongsTo('publisher'),
reviews: DS.hasMany("review")
});

The book model is present at chapter6/example1/app/models/book.js

As you can see here, a book is linked with authors by using DS.hasMany('author'), which means that the author is an array that could refer to zero or more authors.

Similarly, an author can have a similar relationship with the book type, as follows:

import DS from "ember-data";

export default DS.Model.extend({
  firstName: DS.attr('string'),
  lastName: DS.attr('string'),
  fullName: function() {
return this.get('firstName') + ' ' + this.get('lastName'),
  }.property('firstName', 'lastName'),
  bio: DS.attr('string'),
  books: DS.hasMany('book')
});

The author model is present at chapter6/example1/app/models/author.js

Here, you can see that the author refers back to the book type using book: DS.hasMany('book').

As you saw, Ember Data makes it very easy to define relationships between your models. Defining relationships amongst different model objects keeps your code clean and easy to understand. Making proper relationships among your model objects also helps you enforce the Single Responsibility Principle, which states that "Every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class. All its services should be narrowly aligned with that responsibility."

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

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