How to deal with belongs to many relation?


#1

I can’t figure out how to make this work… There are the backend entities ‘events’ and ‘displays’ which are defined as many to many (belongs to many in laravel http://laravel.com/docs/5.1/eloquent-relationships#many-to-many) relations - means tables ‘event’, ‘displays’ and ‘display_event’ are defined and the backend response is like this (excerpt):

{
	"events" : [
		{
			"id" : 111
			"title" : "some event title"
			"displays" : [
				{
					"id" : 10,
					"title": "display 1",
					"pivot" : {
						"event_id" : 111,
						"display_id" : 10,
						"show" : true
					}
				},
				{
					"id" : 12,
					"title": "Massive Big Screen",
					"pivot" : {
						"event_id": 111,
						"dislay_id" : 12,
						"show" : false
					}
				}
			]
		},
		{
			"id" : 222
			"title" : "some other event title"
			"displays" : [
				{
					"id" : 10,
					"title": "display 1",
					"pivot" : {
						"event_id" : 222,
						"display_id" : 10,
						"show" : false
					}
				},
				{
					"id" : 12,
					"title": "Massive Big Screen",
					"pivot" : {
						"event_id": 222,
						"dislay_id" : 12,
						"show" : false
					}
				}
			]
		}
	]
}

The models definitions for event, and display are as follows:

// models/event.js
export default DS.Model.extend({
	title: DS.attr('string'),
    displays: DS.hasMany('display', {async: false}),
   // ...
});

// models/display.js
export default DS.Model.extend({
    title: attr('string'),
    events: DS.hasMany('event', {async: false})
});

What I tried is to define a model for the intermediate table (‘display_event’) like so:

// models/display-event-pivot.js
export default DS.Model.extend({
    display: DS.belongsTo('display', {async: false}),
    event: DS.belongsTo('event', {async: false}),
    show: attr('boolean')
 });

And give the properties ‘display_event_pivot’ to the event and display model as hasMany relation.

And because the pivot date does not contain an id attribute, I just normalized it like so:

// serializers/display-event-pivot.js
normalize: function (typeClass, hash, prop) {
        // give a new computed id here, because i can't figure out, how
        // to handle a belongsToMany relationship properly.
        // The serializer::serialize() method is responsible to remove this id on save/update
        hash.id = hash.display_id + '-' + hash.event_id;

        return this._super(typeClass, hash, prop);
    }

And now I’m kinda lost since when the relationships are extracted, it breaks because ‘display-event-pivot: hasMany’ for event and display expects obviously an array to work with but the pivot is just an object. Making it a belongsTo relation will not work because every event will have the same pivot values (which is wrong). To make it hopefully clear - the result is:

event{111}.displays{10}.display_event_pivot{10-111}.show --> true
event{111}.displays{12}.display_event_pivot{12-111}.show --> false
// these are expected to be false, false but are the same as the both above
event{222}.displays{10}.display_event_pivot{10-222}.show --> true
event{222}.displays{12}.display_event_pivot{12-222}.show --> false

Anyone who can give me some hint on how to solve this?


#2

Have you tried using the EmbeddedRecordsMixin? I think that would make this a whole lot easier (and wouldn’t need the intermediate table).


#3

yep, tried that… well what I do now is: give the pivot an id attribute in the backend. In the display serializer normalize hook use the pivot id as the display id - the displays are now attached correctly to the event. In the application adapter the original display id is then reassigned in the serializer hook… feels hackish… but it works for now.