Backbone does POST instead of PUT on updates when composite key is used
Asked Answered
S

3

7

I'm using a composite key in my model and generate the ID based on my composite key:

app.Assignment = Backbone.Model.extend({
    idAttribute : [ 'personId', 'jobId' ],
    parse : function(resp) {
        resp.id = resp.personId + "_" + resp.jobId;
        return resp;
    }
});

but Backbone still thinks that all instances of Assignment are new, allthough I'm setting the id in the parse method when fetching them from the API. As a result Backbone does no DELETEs and does a POST instead of PUT on updates. How can I work around this or what is the "right way" to do it?

Update:

Looks like replacing resp.id with this.id solves the issue.

Scream answered 4/3, 2013 at 10:39 Comment(4)
Backbone doesn't support composite keys, so defining idAttribute as an array is not valid. Every model must have one id field. What do your resource URLs look like?Bobbyebobbysocks
It does support composite keys: github.com/documentcloud/backbone/pull/1558 actually I solved it by doing this.id = ... instead of resp.ide = ...Scream
Ah, you're using github.com/caseywebdev/backbone-composite-keys. Would've made sense to mention it in the question.Bobbyebobbysocks
doesn't doing that parse thing eliminate the reason to use the composite keys?Viole
H
2

The results of the parse method of a Backbone.Model are passed to the set method, which sets the attributes of the model. The point of confusion for you I think is that the model's ID isn't one of it's attributes; it's one of its properties.

So, what happens is this:

  1. Your raw data comes back from the server and is passed to parse
  2. That same raw data, now augmented with a id attribute, is passed to set
  3. set looks and your idAttribute ([ 'personId', 'jobId' ]) and all of the keys in the raw data
  4. Since none of those keys match the idAttribute, none of them are used as the model's ID, and thus you get your problem.

Your solution of setting this.id inside parse works, but it might cause problems down the road because parse is generally designed to operate on it's input (the raw data), not to modify the model itself; that part is supposed to happen next when set is called. A cleaner solution would instead be to do something like the following:

app.Assignment = Backbone.Model.extend({
    // note that no idAttribute is specified, leaving it as the default "id"
    parse : function(resp) {
        resp.id = resp.personId + "_" + resp.jobId;
        return resp;
    }
}

Or, if you want a different ID attribute ...

app.Assignment = Backbone.Model.extend({
    idAttribute: 'personAndJobId',
    parse : function(resp) {
        resp.personAndJobId = resp.personId + "_" + resp.jobId;
        return resp;
    }
}
Histo answered 27/9, 2014 at 4:35 Comment(0)
P
1

Aside from the idAttribute issues here, you can always force Backbone to use a certain HTTP method via the type options passed to save().

model.save(null, { type: 'put' })

Pyrrho answered 29/12, 2015 at 19:38 Comment(0)
I
0

I've never work with composite ID in Backbone, but I think this could be an easy answer to your problem:

initialize: function() {
      this.set("id", this.generateID());
},
generateID = function () {
    return this.personId + + "_" + this.jobId;
}

With this code in you Backbone model definition you are creating a unique ID for each model and you shouldn't have problems for update and save it (and you don't need to set any idAttribute).

Idolum answered 26/2, 2016 at 13:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.