Question

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
        });
    }
Was it helpful?

Solution

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?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top