Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

model.save() destroys nested collection #131

Closed
ademeter opened this issue May 12, 2014 · 7 comments
Closed

model.save() destroys nested collection #131

ademeter opened this issue May 12, 2014 · 7 comments

Comments

@ademeter
Copy link

Hi!
I have a problem with nested collections using your localStorage adapter.
I want so store GPS-Data whereas one GPS-track is represented with one title and many positions.

Positions are defined as a Backbone.Collection:

TrackModel = Backbone.Model.extend({
        defaults: {
            title: "",
            positions: new PositionsCollection()
        }
    })
PositionsCollection = Backbone.Collection.extend({
        model: PositionModel
    });
PositionModel = Backbone.Model.extend({
        defaults: {
            latitude: "",
            longitude: "",
            timestamp: ""
        }
    });

My data-structure should look like that:

{
    "title": "TrackTitle,
    "positions": [{
        "latitude": "...",
        "longitude": "...",
        "timestamp":"..." }],
        [{
        "latitude": "...",
        "longitude": "...",
        "timestamp":"..."
        }],
        ...
} 

The nesting works fine until i save the complete track with track.save() to localStorage.
Then my PositionsCollection in memory turns into a blank Javascript-Array.
After saving I can't do something like track.get("positions"), which was possible before.

Saving the data to localStorage works. At initialization of my app I'm parsing the json-data like that:

parse: function(response) {
            _.each(response, function(track){
                  track.positions = new PositionsCollection(track.positions);
            });
            return response;
        }

After fetching the data from localStorage everything is fine again.

But I need to keep my positions in memory as a Backbone Collection as well.

Many thanks in advance for your help.
Best

@ademeter
Copy link
Author

Here is the output after logging each track to console (toJSON()):
bildschirmfoto 2014-05-12 um 16 36 35
track no.1 and track no.2 are parsed from localStorage. Track no.3 is the latest track after saving (without parsing again).

@coire1
Copy link

coire1 commented Feb 12, 2015

I've encountered the same problem.
The nested collection turns into a blank Javascript Array when localStorage serializes the model, calling JSON.stringify(model).

According to the manual:

If an object being stringified has a property named toJSON whose value is a function, then the toJSON() method customizes JSON stringification behavior: instead of the object being serialized, the value returned by the toJSON() method when called will be serialized.

So when localStorage serializes the model, it calls model.toJSON(), the default Backbone toJSON, that it simply clones the model's attributes, excluding the nested collection.

A simple solution would be to change the behavior of the model toJSON() to include the nested collection.

I hope this can help you and future readers. 😄

@baoqger
Copy link

baoqger commented Nov 26, 2016

@coire1, I can understand the issue. but can't fix yet. Can you help on this. I meet the same issue on my project
regards
Bao jingjing

@coire1
Copy link

coire1 commented Dec 1, 2016

Hi, it is really an old project but I found the piece of code you need.
In the model that contains the nested collection you have to redefine and override the toJSON method.
The new method has to initialize a new collection and copy the models in it.

toJSON: function() {
  /* Get the array as model attribute */
  var tempNestedModels = this.get('nestedCollection');
  if (!tempNestedModels) {
    /* if are present nested models initialize a new collection */
    nestedModels = new NestedCollection();
  }
  /* for each model in collection copy/filter the attributes needed */
  _.each(nestedModels.models, function(model) {
    model.attributes = _.pick(model.attributes, 'id', 'exampleAttr');
  });
  /* return the original model, filtering out unuseful attributes and adding
  the new collection instead of the original array */
  return _.merge(_.pick(this.attributes, 'id', 'modelAttr'), {
    nestedCollection: nestedModels
  });
}

@scott-w
Copy link
Collaborator

scott-w commented Feb 28, 2017

Hi @coire1, do you happen to have the Backbone version for this? I've synchronised nested collections to the server in Backbone 1.3+ and it's all serialized correctly. If it's fixed upstream, I'll close this ticket.

@coire1
Copy link

coire1 commented Mar 1, 2017

Hello @scott-w, the issue for me happened with Backbone 1.1.2.
It is an old project and I can't test it with the newer version. Hope this helps anyway.
Let me know if I can do anything else.

@scott-w
Copy link
Collaborator

scott-w commented Mar 1, 2017

Hi @coire1 thanks very much for that. I believe Backbone has resolved the issue since then so I'll close this and let anyone comment if they feel it needs to be looked at again.

Best regards,
Scott

@scott-w scott-w closed this as completed Mar 1, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants