0

I've been migrating my app from RethinkDb to Firebase and have run into a wall trying to get my collections to save when calling collection.create(). The odd thing is, I have two instances of Backbone.Firebase.Collection in my app and one of them is able to create new objects properly. The other collection, which is seemingly identical, cannot write data and generates no error messages.

I have two Collections, each with their own type of Model: 1) Projects (Collection) -> Project (Model) 2) Projects (Collection) -> Shots (Collection) -> Shot (Model)

Here are the definitions for the above collections/models:

/* Projects Collection - An ordered list of Projects */
var ProjectModelFirebase = require('../models/projectModelFirebase.js');

module.exports = Backbone.Firebase.Collection.extend({
    model: ProjectModelFirebase,
    firebase: new Firebase(app.fbUrl),
    initialize: function() {
    }
  });

/* Project Model - data layer for a single Project */

module.exports = Backbone.Firebase.Model.extend({
  firebase: new Firebase(app.fbUrl),
  initialize: function() {
  }
});


/* Shots Collection - An ordered list of Shots */
var ShotModelFirebase = require('../models/shotModelFirebase.js');

module.exports = Backbone.Collection.extend({
    model: ShotModelFirebase,
    firebase: new Firebase(app.fbUrl),
    initialize: function() {
    }
  });

/* Shot Model - data layer for a single Shot */

module.exports = Backbone.Firebase.Model.extend({
    firebase: new Firebase(app.fbUrl),
    initialize: function() {
    }
});

In my Projects route (routes file), I bind the collection to the view normally and call this.collection.create with some inputs from the template. I'm able to successfully create projects in this way and they show up in my Forge with no problem. I call the view from my route function:

// Display list of latest projects
    projectsCollectionFirebase = new ProjectsCollectionFirebase();
    var projectsView = new ProjectsView({collection: projectsCollectionFirebase});

In my Project route (routes file), I bind the project collection to the view and retrieve the project's information from Firebase normally:

// Display a single project
    projectModelFirebase = new ProjectModelFirebase({id: project});
    var projectView = new ProjectView({model: projectModelFirebase});

I then proceed (projectView file) to create a new collection of shots:

shotsCollectionFirebase = new ShotsCollectionFirebase();
shotsView = new ShotsView({ collection: shotsCollectionFirebase, project: this.model.get('id') });

The Shots view (ShotsView file) renders the template and input fields for the user to input a shot.

From here, I call this.collection.create when a user clicks the 'Save' button. Backbone recognizes the new model and updates the view accordingly, but Firebase doesn't act on it. There is an error message in the console that states 'Save called on a Firebase model, ignoring.' but I do not have any saves called out explicitly in my code.

I've tried turning on debugging and noticed that the 'projects' create command causes this message:

r:0: update {"path":"/projects/test","value":{"shots":null}}

Whereas the 'shots' collection does not ever trigger an 'update' event.

The files are nearly identical. The only thing difference I can spot is that the first example has only one collection loaded at a time whereas the second example loads a collection, grabs the data, then loads another collection as a result.

Any help would be appreciated.

You can find the full code for the project in my repo here: https://github.com/bdickason/shots/tree/firebase

Brad Dickason
  • 492
  • 4
  • 10

1 Answers1

2

There are two modes of operation in Backfire, one with models/collection that have the word 'Firebase' in them, eg: Backbone.Firebase.Model/Backbone.Firebase.Collection; and the other mode that uses regular backbone collections and models but have the 'firebase' property defined on them that overrides the backbone sync() method.

These two modes should not be mixed and matched. For example, if you're using a Backbone.Firebase.Collection, all the models in that collection will automatically be synchronized with the server any time a change is made to any model (same for Backbone.Firebase.Model). Calling save, or sync doesn't do anything because the changes are saved and synced in realtime as they happen.

Sometimes this isn't what you want in the app, for example, you want the user to explicitely click a save button before saving anything to Firebase. In these cases, it's best to use a regular Backbone collection or model, and simply provide the firebase property on them. You then need to call sync or save explicitely to put any changes on the local model/collection into Firebase.

Anant
  • 7,408
  • 1
  • 30
  • 30
  • That did it! I've now unearthed a new error: 'Uncaught TypeError: Cannot set property '_remoteAttributes' of undefined' which happens when Firebase tries to load the data... but I'm happy to move on to solving this new problem. Thanks for your help!! – Brad Dickason Feb 11 '14 at 04:43
  • To add extra info for anyone else who encounters this, the proper setup is: Collection (Backbone.Firebase.Collection) -> Model (Backbone.Model) This allows the collection to properly sync. – Brad Dickason Feb 11 '14 at 05:20
  • Are you still encountering the _remoteAttributes error? – Anant Feb 11 '14 at 17:44
  • 1
    Nope, I fixed this by making my collection a firebase.collection and my model a regular backbone.model which resolved it. Is this the optimal setup? – Brad Dickason Feb 12 '14 at 06:21