Outside of the basic implementation of a Sencha Touch model, there’s some more advanced stuff you an do (check out how to use the convert function on fields for another example). Model associations in Sencha Touch are a convenient way to create relationships between models. You may be familiar with relationships such as the following:
One-to-One one object belongs exclusively to another (i.e. one house to one owner)
One-to-Many one object belongs to many other objects (i.e. one product to many stores)
Many-to-Many a number of objects belongs to a number of other objects (i.e many people to many groups)
Fortunately, Sencha gives us some out of the box functionality to represent these relationships in our models. If you take a look at the Ext.data.association.Association class you will notice several different relationships that are available, namely:
- Has Many
- Belongs To
- Has One
Has Many takes care of our one-to-many relationship and could be created as shown in the documentation as follows:
Ext.define('Product', {
extend: 'Ext.data.Model',
config: {
fields: [
{ name: 'id', type: 'int' },
{ name: 'user_id', type: 'int' },
{ name: 'name', type: 'string' },
],
},
});
Ext.define('User', {
extend: 'Ext.data.Model',
config: {
fields: [
{ name: 'id', type: 'int' },
{ name: 'name', type: 'string' },
],
// we can use the hasMany shortcut on the model to create a hasMany association
hasMany: { model: 'Product', name: 'products' },
},
});
While nothing special is happening in the Product model, in the User model we are defining a hasMany relationship. We are declaring that the relationship is on Users to Products and will take the name of products. With this relationship defined, a function is created on User instances for us that we can use to grab the products related to that user. It can be retrieved in the following way:
var products = user.products;
Where user is an instance of the User model.
Similarly belongsTo takes care of the many-to-one association and hasOne takes care of the one-to-one association. Looking good so far but there’s one relationship missing… there’s no many-to-many association in Sencha Touch!
This was an exercise in frustration for me, surely thousands of people have had the need to implement a many-to-many relationship and a solution would exist out there. I had no luck finding any kind of ‘proper’ or ‘official’ solution but there were certainly discussions around how to implement the relationship.
After quite a bit of research it seemed that the best option was to create an additional new model to represent the relationship between the two other models – like a junction table in a relational database. Rather than try to explain this in abstract terms, I’ll walk you through the specific example I created.
In my case I had Users and Groups. This was a many-to-many relationship – I needed multiple users to belong to multiple groups. Naturally I had a User model and a Group model, but I needed to create an additional UserGroup model.
My UserGroup model looked like this:
Ext.define('MyApp.model.UserGroup', {
extend: 'Ext.data.Model',
requires: ['Ext.data.identifier.Uuid'],
config: {
identifier: {
type: 'uuid',
},
fields: [
{ name: 'userId', type: 'int' },
{ name: 'groupId', type: 'int' },
],
proxy: {
type: 'ajax',
api: {
//api links
},
reader: {
rootProperty: 'usergroups',
},
},
},
});
and in my User model I added the following hasMany relationship:
hasMany: {
model: 'MyApp.model.UserGroup',
name: 'userGroups',
foreignKey: 'userId'
},
Now I could run the following code to load a store containing records of every group a user belonged to (where currentUser is an instance of the User model):
currentUser.userGroups().load({
scope: this,
callback: function (records, operation, success) {
Ext.each(
records,
function (association) {
console.log(association.getData().groupId);
},
this
);
},
});
Problem solved! This isn’t a perfect solution by any means (in fact it’s really only half implemented – I still need to add the relationship the other way from Groups to Users!) but it serves the purpose I need it to for now. If you have a better way of implementing the many-to-many relationship please post it in the comments below!