1
votes

I see several questions on SO attempting to solve this problem of sending POST requests to nested API resource routes.

See: - [Sending REST requests to a nested API endpoint URL using Ember Data(Sending REST requests to a nested API endpoint URL using Ember Data) - Custom request URLs in Ember model

I've started overloading the createRecord, updateRecord, and deleteRecord methods on the RESTAdapter to attempt some sort of hackery solution to building the correct URL. Now, using a method similar to this is the route I've taken so far.

Here is the updateRecord method in their solution:

App.UserAdapter = DS.RESTAdapter.extend({

    updateRecord: function(store, type, record) {

        if(!record.get('parent') || null === record.get('parent')){
            return this._super(store, type, record);
        }

        var data = {};
        var serializer = store.serializerFor(type.typeKey);

        var parent_type = record.get('parent');
        var parent_id = record.get(parent_type).get('id');
        var child_parts = Ember.String.decamelize(type.typeKey).split('_');

        var path = Ember.String.pluralize(parent_type) + '/' + parent_id + '/' + Ember.String.pluralize(child_parts.pop());

        serializer.serializeIntoHash(data, type, record);
        var id = record.get('id');

        return this.ajax(this.buildURL(path, id), "PUT", { data: data });
    }
    ....
});

This method should work great in tandem with adding the parent type to the model and ensuring the related parent model id is also represented on the model. For PUT and DELETE requests, this shouldn't be a problem, as we already have the parent ID relation on the object in store.

Project model:

App.ProjectModel = DS.Model.extend({
    name: DS.attr('string'),
    createdAt: DS.attr('date'),
    updatedAt: DS.attr('date'),
    workspace : DS.belongsTo('workspace'),
    parent: 'workspace',
    ....
});

Where this method appears to go awry for me is in creating new resources with a post. I've attempted it, but since the payload hasn't been returned from the API server with the related parent ID, I actually don't have access to it.

Here's my crappy first attempt, that doesn't work. The workspace id always returns null.

createRecord: function(store, type, record) {
    if (!record.get('parent') || null === record.get('parent')){
        return this._super(store, type, record);
    }

    var data = {};
    var serializer = store.serializerFor(type.typeKey);

    var parent_type = record.get('parent');
    var parent_id = record.get(parent_type).get('id');

    var path = Ember.String.pluralize(parent_type) + '/' + parent_id + '/' + type.typeKey);

    serializer.serializeIntoHash(data, type, record, { includeId: true });

    return this.ajax(this._buildURL(path, null), "POST", { data: data });
},

Got any thoughts on how I can get the parent ID, before I have a saved record?

1
Looks like you're doing a lot of work to do this in Ember Data, is there any reason why? Ember works perfectly fine outside of Ember Data. You might want to include your models, it's a bit difficult to understand the context.Kingpin2k
I had a somewhat related problem, and I would suggest you look at nesting your models to correspond with your nested api endpoints. For example, if your api endpoint is /foo/bar, and '/foo/baz', then you would probably have bar, baz as your models under the /models/foo directory on the ember side. This will namespace the models and the api that gets constructed will have '/foo/' as it's prefix. You might have to write your own serializer and nest your routes properly for this to work, depending on your models but overriding createRecord and other hooks seems a bit too hacky.Hrishi
@Kingpin2k, I've certainly thought hard about doing the ajax requests manually and using store.pushPayload('type', data) to make this work. For now, it's boiling down to trying to stay within the boundaries of ember-data. Maybe I'm being too idealistic?ToddSmithSalter
If you log out the workspace record does it have anything? What's the original data that populates those records look like?Kingpin2k

1 Answers

1
votes

I am the author of the solution you cited in your question.

What does your model hook look like in the route where you are creating the new ProjectModel?

Assuming your Workspace route looks something like:

App.WorkspaceRoute = Ember.Route.extend({
    model: function (params) {
        return this.store.find('workspace', params.id);
    }
});

Then your Workspace Project add/create route's model hook would need to be something like:

App.WorkspaceProjectAddRoute = Ember.Route.extend({
     model: function () {
            var workspace = this.modelFor('workspace');

            return this.store.createRecord('project', {
                workspace: workspace
            });
        }
    }

I hope this makes some sense...