Adding queryParams to ember-data save


#1

Hey!

I have a design question again. We need to pass a query param to our PUT route. This query param is called forceOverwrite and should be true/false if the data should overwrite existing data on the server. As I can not pass a parameter to the ember-data save method I think I have to extend ember-data somehow. I achieved it the following way (but I’m not sure if it is a good idea to do so): by the way I’m using ember-cli:

In the controller:

        // ...
        // determine if overwrite is true or false
        // ...
        self.get('model').save({
            forceOverwrite: overwrite
        }).then(function (res) {
            // ...
        }, function (err) {
            // ...
        });

In initializers/reopen-model.js

    initialize: function () {
        DS.Model.reopen({
            save: function (queryParams) {
                if (!Ember.isEmpty(queryParams)) {
                    this.set('queryParams', queryParams);
                }
                return this._super();
            }
        });
    }

And in adapters/application.js

export default DS.RESTAdapter.extend({
    // ....
    buildURL: function (type, id, record) {
        var url = this._super(type, id, record);
        if (Ember.isEmpty(record)) {
            return url;
        }
        var queryParams = Ember.get(record, 'queryParams');
        if (!Ember.isEmpty(queryParams)) {
            for (var key in queryParams) {
                if (queryParams.hasOwnProperty(key)) {
                    var seperator = (url.indexOf('?') === -1) ? '?' : '&';
                    url += seperator + key + '=' + queryParams[key];
                }
            }
        }
        return url;
    }
});

Is this approach good? I’m afraid that I’m running into some troubles I don’t see right now. Especially I’m not sure if it’s a good idea to append data to the record?

What do you think, is this solution good or could it be developed better?

Thanks for your opinions Bye


#2

Hi @tschoartschi Have you found an answer to your question? I need to do a similar thing with POST request.


#3

I used “ember-data-url-templates”.

This offers convenience methods to construct a url for each type of request. Within the adapter, this offers hooks in which you can parse the {query} properties, else just attach them to the call. ie:

    queryUrlTemplate: '{+host}/{retailerId}/{storeId}/product_catalog/products{?query*}',
    updateRecordUrlTemplate: '{+host}/{retailerId}/{storeId}/product_catalog/products{?query*}',

    urlSegments: {
        // host required to be defined here for UrlTemplates
        // as host is an alias for window.location.host
        // and UrlTemplates is designed to operate outside of 
        // global defaults, such as ApplicationAdapter.host
        host() {
            return config.apiBaseUri;
        },
        retailerId() {
            return this.get('routingService.retailerId');
        },

        storeId() {
            return this.get('routingService.storeId');
        }
    }

Each of these urlSegments offers a hook in which you can manage forceOverwrite, including preventing any data transfer/request to server if desired.

Alternatively, you can perform the same using “urlForQuery(query, modelName) or urlForCreateRecord(modelName, snapshot)” on a custom Adapter, (say called forcedOverwriteAdapter) which you can pass the model (forcedOverwriteModel a single model copy of the one you wish to save) and query you wish to combine, and urlForQuery instead calls the ApplicationAdapter.ajax() to PUT as per requirement. Better still, urlForCreateRecord:

    this.store.createRecord('forcedOverwrite', {
        belongsTo       : modelToSave,
        modelName       : 'nameOfModel',
        forcedOverwrite : query.forcedOverwrite
    });

    // adapter
    urlForCreateRecord(modelName, snapshot) {
        // hijack this to instead save the associated model, utilising snapshot
    }