Imagine we have two entities, stored in a relational database as:
person(id, name)
friendship(id, personAID, personBID, strength)
Here we can see that two people can be friends and a "strength" (some numerical value) will be given to that friendship. If persons 1 and 2 are friends, then we have the following entry in the friendship table:
xyz | 1 | 2 | 50 |
note that the following corresponding entry does not exist:
abc | 2 | 1 | 50
Only one entry is created per "friendship".
What I struggle with is how to model this in the ember app. A "person" can have many friendships, and a "friendship" relates exactly 2 people.
// models/person.js
DS.Model.extend({
name: DS.attr('string'),
friendships: DS.hasMany('friendship', {inverse: 'friends'})
});
The friendship objects are serialized as an array of
{
id: 'abc',
friends: ['1', '2'],
score: '50'
}
so:
// models/friendship.js
DS.Model.extend({
friends: DS.hasMany('person', {inverse: friendships}),
personA: Ember.computed(friends, function() {
return this.get('friends').objectAt('0');
}),
personB: Ember.computed(friends, function() {
return this.get('friends').objectAt('1');
}),
getFriend: function(id) {
if (id === this.get('personA.id')) {
return this.get('personB');
}
if (id === this.get('personB.id')) {
return this.get('personA');
}
return null;
},
score: DS.attr('number')
});
The implementation of the friendship model feels hacky for lots of reasons. First of all, a friendship does not "have many" friends. It has exactly two. However, if I change the implementation to:
DS.Model.extend({
personA: DS.belongsTo('person'),
personB: DS.belongsTo('person'),
...
});
then I'm not sure how to model the "hasMany" relationship of person => friendship. What would the 'inverse' field be set to, for instance?
The "score" field is complicating things. If that didn't exist then this would be a reflexive relation within the "person" model, but the relation has additional data and must be able to be represented as its own entity.
Also, given the situation where I want to list all of the friends of a given person, along with the strength of that friendship, the "getFriend()" function is required. This function smells a bit to me and I can't quite put my finger on why.
So my question is, what do you see as an effective way to model two-way symmetric relationships that contain additional data such as the "score" field? I can't change anything about how the data is stored in the DB, but I do have control over everything else, so I can transform the data into any structure on the way out of the DB and into the Ember client.
Ember and Ember-data 2.x
Aucun commentaire:
Enregistrer un commentaire