Add option to use HTTP PATCH method for updates #796

Closed
wants to merge 1 commit into
from

Projects

None yet

6 participants

@jasonkriss
Contributor

I'm not sure if this is the best way to accomplish this, but I think it'd be nice to allow this option. Especially considering that PATCH will be the primary update method for Rails 4.

@bobbus
Contributor
bobbus commented Mar 11, 2013

I think the point of PATCH is to only send the updated data, then I would think a proper implementation would only send modified attributes in the request. Sadly, the dirtiness behavior cannot let us do that for now.

@tchak
Member
tchak commented Mar 11, 2013

Sadly, the dirtiness behavior cannot let us do that for now.

@bobbus I think this is not true, we do have information about changed attributes.

@bobbus
Contributor
bobbus commented Mar 11, 2013

@tchak , for now, I believe we only store the dirty state of a record, not the list of modified attributes.
You may be right as we can compare the last data received from the API and the record json serialization and figure out what did change, is it what you think about ?
I do not see another way to do it for now, if there is one it could help to fix #646

@tchak
Member
tchak commented Mar 11, 2013

@bobbus we do keep detailed infos for attributes changes, but there is no public api yet to get to it

https://github.com/emberjs/data/blob/master/packages/ember-data/lib/system/model/states.js#L183-L194

@bobbus
Contributor
bobbus commented Mar 11, 2013

@tchak , thanks I thought this was lost after the sync() , will look further into this soon.

@jasonkriss
Contributor

Good points. I think it'd be great to be able to only send the dirty attributes back to the server. That being said, I think PATCH is still valid with the current implementation. PUT is meant for complete replacement of a record and that's not what is happening with an update.

@igorT
Member
igorT commented Apr 8, 2013

We would love to have PATCH that would only send the changed attributes. I think the current internals support that but they will be refactored soon so I would hold off on that. I don't think that having a PATCH that behaves like a PUT would be that useful/would be confusing. If you need it for your use case, overwriting the RESTAdapter should work.

@igorT igorT closed this Apr 8, 2013
@jasonkriss jasonkriss deleted the jasonkriss:patch branch Apr 9, 2013
@briangonzalez

@igorT What's the latest on this?

@valberg
valberg commented Jul 8, 2014

I have extended DS.RESTSerializer and DS.RESTAdapter like this (props to http://discuss.emberjs.com/t/saving-models-with-only-changed-attributes-relationships/3568):

export default DS.RESTSerializer.extend({
  serialize: function (record, options) {
    var self = this;
    var json = {};
    var inFlightAttrs = Object.keys(record.get('_inFlightAttributes'));

    if(options && options.includeId) {
      if(record.get('id')) {
        json[this.get('primaryKey')] = record.get('id');
      }
    }

    record.eachAttribute(function (key, attribute) {
      if(inFlightAttrs.indexOf(key) != -1) {
        self.serializeAttribute(record, json, key, attribute);
      }
    });

    record.eachRelationship(function (key, relationship) {
      if(relationship.kind == 'belongsTo') {
        self.serializeBelongsTo(record, json, relationship);
      } else if(relationship.kind == 'hasMany') {
        self.serializeHasMany(record, json, relationship);
      }
    });

    return json;
  }
});
export default DS.RESTAdapter.extend({
  updateRecord: function(store, type, record) {
    var json = {};
    var serializer = store.serializerFor(type.typeKey);
    serializer.serializeIntoHash(json, type, record);
    var id = record.get('id');
    return this.ajax(this.buildURL(type.typeKey, id), "PATCH", { data: json });
  },
});

It works, and only sends those attributes that have been changed. I'm not sure if there are any pitfalls though.

It would definitely be awesome to support doing partial updates using PATCH. Maybe it could be an option one can give to .save()? Like record.save(partial=true) and then it will use PATCH instead of PUT.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment