Added support for composite keys as the `idAttribute` #1558

wants to merge 2 commits into


None yet

6 participants


I like to create Backbone models for my join tables, but I don't want to throw an unnecessary id field in the table when a composite key is ideal. This commit makes it possible to set idAttribute to an array of attribute names. See the tests for examples. Please let me know if there is a case where this breaks, but all tests passing so far.


Sounds fine -- but you shouldn't have to patch Backbone to support this. If you want to find a model by a unique combination of userId and taskId -- just use find. The "composite keys" in this patch would break URL compatibility, the .get api, and so on.

@jashkenas jashkenas closed this Aug 17, 2012

There's no way to guarantee uniqueness in a Collection of composite key join models without manually iterating through after each .add since they aren't indexed by a single id. Could you elaborate on how this breaks URL compatibility? And I don't think .get will ever be used on a composite key collection, but id generation is crucial for uniqueness.


You could use parse instead.

var Model = Backbone.Model.extend({
  parse: function(resp) { = resp.x + resp.y;
    return resp;

Backbone assumes a RESTful API structure by default, and that resources all have a single unique key. Urls for models are built up by grabbing the collection url or the model's urlRoot and appending that model's id.


@braddunbar I like that. Obviously it will break if rest.x or resp.y changes, but then again, they'll probably never change.

resources all have a single unique key

I thought about adding an id field to the join table for just this reason, but I just can't justify that as an id on a join table would increase too rapidly.

I'll go with a parse-like solution for now and see how it works out. Thanks!


Another way to go, if you just want to validate uniqueness, is to, ahem, use validate.


In case anyone stumbles across this, I ended up using

class app.Model extends Backbone.Model
  initialize: ->
    @_previousId = @id = @_generateId()

  change: ->
    @_previousId = @id
    @id = @_generateId()
    super arguments...

  _generateId: ->
    return get @idAttribute unless @compositeKey
    vals = []
    for index in @compositeKey
      return undefined unless (val = @get index)?
      vals.push val
    vals.join '_'

class app.Model.Collection extends Backbone.Collection
  _onModelEvent: (event, model, collection, options) ->
    if model and event is 'change' and isnt model._previousId
      delete @_byId[model._previousId];
      @_byId[] = model if
    super arguments...

class app.Appointment extends app.Model
  compositeKey: ['doctorId', 'patientId']

class app.Appointment.Collection extends app.Model.Collection
  model: app.Appointment

I haven't tested it yet but in theory this solves my problem.


I am also looking for this functionality since I have different types of models in the same collection.

What about allowing a callback for the idAttribute property, like the url and urlRoot do at this moment, then the ID could be created on initialization / update etc?

Please shoot some holes in this idea =)


I've created a plugin for this at backbone-composite-keys if you wanna check that out. You simply provide an array of attributes as the idAttribute and internally the id is maintained as 'id-id' or 'id-id-id' etc...

madtyn commented Mar 20, 2014

Hello, a Javascript beginner here.

I'm working in a project in which we're looking for using composite-ids and we're interested in using this backbone-composite-keys js library.

Could you please provide some small example on how to declare a Backbone Model and how to create it.

I know there is a test, but is in made in Coffee language and I don't understan it very well. I would be very grateful if someone could write in JS a minimal example of a simple object declaration and an instantiation sentence with 'new'.

Thanks very much in advance.


@madtyn Unfortunately I haven't kept that library up to date, but you're in luck! Support for composite keys actually just landed in master via generateId. Check out #2985 for more info.

madtyn commented Mar 20, 2014

I'm checking. Thank you very much.

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