Ember-Data is a library for managing model data in Ember.js applications. It provides many of the facilities you’d find in server-side object relational mappings (ORMs) like ActiveRecord, but is designed specifically for the unique environment of JavaScript in the browser.
When an API is represented using Ember Data models, adapters and serializers, each association simply becomes a field name. This encapsulates the internal details of each association, thereby insulating the rest of your code from changes to the associations themselves.
Routes and Models
-
In Ember.js, the router is responsible for displaying templates, loading data, and otherwise setting up application state. The router matches the current URL to the routes that you’ve defined, so a route is responsible for specifying the model that a template is to display.
App.ItemsRoute = Ember.Route.extend({ model: function(){ // GET /items // Retrieves all items. return this.modelFor('orders.show').get('items'); } });
Ember Data provides DS.Model which is a subclass of Ember.Object and adds capabilities like saving or updating a single record or multiple records for convenience.
To create a new Model, we create a subclass of DS.Model (e.g., App.User = DS.Model.extend({})).
Model Attributes
-
Basic model attributes are defined using DS.attr; e.g.:
App.User = DS.Model.extend({ firstName: DS.attr('string'), lastName: DS.attr('string') });
Only fields created by DS.attr will be included in the payload that’s passed to the server for creating or updating records.
DS.attr accepts four data types: string, number, boolean and date.
One-to-one Relationships
-
Say, for example, that each User has a unique Profile. We can represent this relationship in Ember Data using DS.belongsTo on both User and Profile:
App.User = DS.Model.extend({ profile: DS.belongsTo('profile', {async: true}) }); App.Profile = DS.Model.extend({ user: DS.belongsTo('user', {async: true}) });
One-to-many and Many-to-one Relationships
-
Say we have a model where a Post has many Comments. In Ember Data, we can represent this relationship with DS.hasMany('comment', {async: true}) on Post and DS.belongsTo('post', {async: true}) on Comment:
App.Post = DS.Model.extend({ content: DS.attr('string'), comments: DS.hasMany('comment', {async: true}) }); App.Comment = DS.Model.extend({ message: DS.attr('string'), post: DS.belongsTo('post', {async: true}) });
Many-to-many Relationships
- Say that in our model an Author may have multiple Posts and a Post may have multiple Authors.
To represent this relationship in Ember Data, we can use DS.hasMany('author', {async: true}) on Post and DS.hasMany('post', {async: true}) on Author:
App.Author = DS.Model.extend({
name: DS.attr('string'),
posts: DS.hasMany('post', {async: true})
});
App.Post = DS.Model.extend({
content: DS.attr('string'),
authors: DS.hasMany('author', {async: true})
});
Polymorphic Relationships
-
let’s say that two types of Providers (“Shop” and “Bookstore”) are defined:
App.Shop = App.Provider.extend({ status: DS.attr('string') }); App.BookStore = App.Provider.extend({ name: DS.attr('string') });
Here’s where Ember Data’s support for polymorphic relationships will come in handy. Ember Data supports one-to-one, one-to-many, and many-to-many polymorphic relationships. This is done simply by adding the attribute polymorphic: true to the specification of the association. For example:
App.Provider = DS.Model.extend({
providerOrders: DS.hasMany('providerOrder', {async: true})
});
App.ProviderOrder = DS.Model.extend({
provider: DS.belongsTo('provider', {polymorphic: true, async: true})
});
The above polymorphic flag indicates that there are various types of Providers that can be associated with a ProviderOrder (in our case, either a Shop or a Bookstore).
This is just some basic about how Ember-Data handles models and their relationships. In next article we'll learn about SideLoading, Links and Active Model Serializer and Adapter.