0

I just started working with backbone.js and couchdb using a simple 'counter' application to learn the ropes. A version that uses localstorage can be found here: demo fiddle. It is a simple application that displays a counter that can be incremented and decremented. The counter's value is stored in the database. In the referenced version, I am using localstorage, which seems to work just fine.

The problem arrises when I convert my example to use couchdb. Therefore, I created a couchapp and adapted the code to work with the backbone-couchdb connector. I also included the db config attributes (as mentioned here). The relevant (adapted) part of the code is found below (which just boils down to including the url attribute).

var Counter = Backbone.Model.extend({

  defaults: {
    countervalue: 0
  },

  initialize: function() {
     _.bindAll(this);
  },

  increment: function() {
     this.save({countervalue: this.get('countervalue') + 1});
  },

  decrement: function() {
     this.save({countervalue: this.get('countervalue') - 1});
  }
});

var Counters = Backbone.Collection.extend({

 model: Counter,

 url : "counters",

 initialize: function() {
    this.fetch();
 }
});

However, whenever I increment or decrement the counter, the following error arrises: "A "url" property or function must be specified". From the documentation, I understood that the Model gets its url from the Collection in which it is contained. This does not seem to be the case? What am I doing wrong?

Perhaps another relevant part of the app is where I instantiate the Counter model (it can also be seen in the demo fiddle); the initialize method of the AppView:

    initialize: function() {
        var currentCounter;
        if (theCounters.size() > 0) currentCounter = theCounters.last();
        else {
            currentCounter = new Counter();
            theCounters.push(currentCounter);
        }
        this.counterview = new CounterView({
            model: currentCounter
        });
    }
Johan B
  • 2,461
  • 14
  • 16

1 Answers1

1

I haven't worked with CouchDB and Backbone.js together, but I guess the workaround is the same than in this explaination.

When using the localStorage adapter, you have to provide a localStorage attribute on the Collection and that's the only place where you type URLs (the root one for the Collection, in fact). However, when not using this adapter and attempting to sync the model, this model needs an URL because now the Collection has none. You are right when providing a URL property to the Collection, but that's used when synchronizing the whole Collection and not when synchronizing an individual model.

To make it work you may either provide an URL for the model (remember it can be a function and not just a String) or you can use the urlRoot attribute, and that urlRoot is what we would understand as the "Collection's URL" (where it will append its id). If urlRoot was /counters and you had a model with an id of 1, then the final URL (it does it for you) will be /counters/1, for example.

Edit:

You may check this question in case you didn't, even though it isn't about CouchDB, but it may throw some light on the issue: How do I fetch a single model in Backbone?

Community
  • 1
  • 1
Meta
  • 346
  • 2
  • 12
  • Thanks for your response. Adding the urlRoot property fixes the error but does not seem to make the behavior correct (i.e. I do not get the persisted model when restarting the app -- but this might be due to other things too). In any case, I'm very confused about what you mention about the url property since it seems to contradict the doc: http://documentcloud.github.com/backbone/#Model-url or does it not? thx for any further clarification. – Johan B Dec 26 '12 at 08:38
  • From what I see after double checking the docs, you were so right when setting the `url` attribute of the Collection and thinking that it would be all you needed. However, from what I understand and know so far, that attribute will only work when synchronizing the whole Collection (that is, if you have 3 models with `1`, `2` and `3` as `id`, collection will synchronize them to `root/1`, etc). However, your code saves models individually, so they don't really know in which collection they are. That's why you need to provide `url` or `urlRoot` in the model. It's more or less what the doc says ^^ – Meta Dec 26 '12 at 10:00