Saturday, October 1, 2011

Be Careful Overriding ID in Backbone.js

‹prev | My Chain | next›

I think I have my Backbone.js calendar application entirely switched over to faye as the persistence layer. I can create, update, delete appointments from my calendar:
There are still a couple of minor issues that I will begin tackling tonight.

The first issue involves updating newly added appointments. At some point this month, I am going to want to get some sleep:
Much is working at this point. Backbone is able to save, via Faye. It receives confirmation. New models are created and added to a Backbone collection. And a new view is created, which places a new UI element on the calendar:
But, what if I decide that, instead of a nap, maybe it is a better idea to simply go to bed early:
Even the edit-appointment view is properly attached to the appointment-in-the-month view. But, after clicking OK to save this update, I see not one, but two admonitions to get to bed early:
Even stranger, when I reload the page, I have one nap and one early-to-bed:
The add-appointment view was not converted to a singleton view, so I give that a try. It has no effect. So I drop into the Chrome Javascript debugger:
Hrm... well, I suppose that makes sense. If the model is new, then it ought to be created when saving. But why is it new?

After quite a bit more stepping through debugger statements, I finally come across this gem in the model initializer:

          initialize: function(attributes) {
            this.id = attributes['_id'];
          },
I need that for initializing from the CouchDB database, but not from CouchDB updates. Ugh. I think this is another defect in my non-faye solution. Regardless, the solution is simple enough:
          initialize: function(attributes) {
            this.id = attributes['_id'] || attributes['id'];
          },
With that fixed, I still have a few other little things to clear out. Tomorrow.

Day #

2 comments:

  1. It's a lot better to override the persistence method via overriding Backbone's sync method, then you can leave the model and collection initializers alone.

    http://documentcloud.github.com/backbone/#Sync

    If you setup that for couch, then you can use "save" and "create" and "delete" naturally on objects and it will go through your sync method.

    ReplyDelete
  2. I did override Backbone.sync -- at your earlier suggestion :)

    I am overriding initialize() so that models fetch'd from CouchDB, which have "_id" instead of "id" attributes, will work. I don't think I can avoid that when working with Couch -- can I?

    This trouble was caused because I manually set "id" in the backend for creates.

    ReplyDelete