Akos K
Akos K

Reputation: 7133

Persist ember model with embedded record

I have the following ember models:

App.Location = DS.Model.extend({
    street: DS.attr('string'),
    city: DS.attr('string'),
    area: DS.attr('string'),
    lat: DS.attr('string'),
    lng: DS.attr('string'),
    report: DS.belongsTo('report', {embedded: 'always'})
});

App.Report = DS.Model.extend({
    title: DS.attr('string'),
    description: DS.attr('string'),
    reg_num: DS.attr('string'),
    location_str: DS.attr('string'),
    location: DS.belongsTo('location', {embedded: 'always'})
});

In App.ReportController when I try to save the report I also want to embed the location object in the request payload. So far I tried the following code:

App.ReportController = Ember.ObjectController.extend({
    actions: {
        saveReport: function(record) {
            var self = this,
                report = this.get('model'),
                location = this.store.createRecord('location', {
                               lat: this.get('lat'),
                               lng: this.get('lng')
                           });
                report.set('location', location);
                report.save().then(function (result) {
                    self.transitionToRoute('list');
                });
            }
        }
    }
});

However in the request payload location is always location: null.

How to add location to the request payload?

Upvotes: 0

Views: 159

Answers (2)

Akos K
Akos K

Reputation: 7133

Putting composite JavaScript objects in the payload shouldn't be rocket science, I hope there is a less complicated way to achieve this.

Make sure that you don't have belongsTo defined for both relations because you will end up with stack overflow:

App.Location = DS.Model.extend({
    street: DS.attr('string'),
    city: DS.attr('string'),
    area: DS.attr('string'),
    lat: DS.attr('string'),
    lng: DS.attr('string')
});

App.Report = DS.Model.extend({
    title: DS.attr('string'),
    description: DS.attr('string'),
    reg_num: DS.attr('string'),
    location_str: DS.attr('string'),
    location: DS.belongsTo('location', {embedded: 'always'})
});

I had to configure the PostSerializer and override the serializeBelongsTo to make this work

App.PostSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
    attrs: {
        location: {embedded: 'always'},
        report: {embedded: 'always'}
    }
});

DS.JSONSerializer.reopen({
    serializeBelongsTo: function(record, json, relationship) {
        var key = relationship.key,
            belongsToRecord = Ember.get(record, key);

        if (relationship.options.embedded === 'always') {
            json[key] = belongsToRecord.serialize();
        } else {
            return this._super(record, json, relationship);
        }
    }
});

Upvotes: 0

Microfed
Microfed

Reputation: 2890

Maybe I'am missing something, but I know two different ways of handling embedded records (ember-data >= 1.0.0-beta):

  1. Rewriting DS.Adapter's methods: serialize/extract*/normalize and others, - to set JSON payload in a way which Ember can work with.
  2. Using DS.EmbeddedRecordsMixin for configuring DS.Serializer.

I can assume you get location: null because of default DS.Serializer's behavior with serializing relationships: Ember expects id value in belongTo property and list of ids in hasMany property. LocationModel doesn't have an id after creating and before saving into server database. When default serializer tries to form an outgoing json payload while saving ReportModel with attached newly created LocationModel, it gets id of LocationModel (null) and puts that id in location property.

Upvotes: 1

Related Questions