1

I have following models:

App.Parent = DS.Model.extend({
  foo: DS.attr('string'),
  children: DS.hasMany('child', {async: true})
});

App.Child = DS.Model.extend({
  bar: DS.attr('string')
});

I filled them with some fixture data:

App.ApplicationAdapter = DS.FixtureAdapter.extend();

App.Parent.FIXTURES = [
  {
    id:0,
    foo: 'parent',
    children: [0,1]
  }
];

App.Child.FIXTURES = [
  {
    id: 0,
    bar: 'child 0'
  },
  {
    id: 1,
    bar: 'child 1'
  },
  {
    id: 2,
    bar: 'child 2'
  }
];

After I do some changes to the children relation, how can I rollback children relation to its latest saved state?

I push new child to manyArray in the following way:

this.store.find('child', 2).then(function(child){
  model.get('children').pushObject(child);
})

This does change the relation (I see new child in my view), but parent record does not become dirty. Thus, when I try model.rollback() it does nothing. I also tried solution I found here How to rollback relationship changes in EmberData which is adding model.send('becomeDirty') before rollback, but it does not help.

Maybe I am adding children to my relation in a wrong way?

Thanks!

Community
  • 1
  • 1
VoloD
  • 77
  • 2
  • 8

4 Answers4

2

I used this to rollback related records that are dirty.

App.ParentRoute = Ember.Route.extend 
  model: ->
    @get('store').createRecord('parent', child: @get('store').createRecord('child'))
  actions:
      willTransition: (transition) ->
        rollbackRecords(@)

rollbackRecords = (context) ->
  if context.get("controller.content.isDirty")
    relationships = Ember.get(App[context.get('controller').resourceName], "relationshipsByName")
    content = context.get('controller.content')
    relationships.forEach (name, relationship) ->
      relatedModel = content.get(name)
      relatedModel.rollback() if relatedModel? and relatedModel.get('isDirty')
    content.rollback()
  true
webguy
  • 41
  • 4
2

Here is some code that will rollback a model, as well as it's relationships that I use:

    var model = this.get('model');
    var relatedModel, relatedModels;
    model.constructor.eachRelationship(function (key, relationship) {
        if (relationship.kind === 'hasMany') {
            relatedModels = model.get(key);
            if (relatedModels) {
                relatedModels.invoke('rollback'); //since this is an array, need to call the rollback function differently
            }
        }
        else {
            relatedModel = model.get(key);
            if (relatedModel) {
                relatedModel.rollback();
            }
        }
    });
    model.rollback();

Hope this helps

2

I believe the other answers listed here only partially solve this problem. If you add a new related model or remove an existing one, rollback should reverse those as well and I believe the other answers don't address this. Here is a complete solution that provides proper dirty checking and a complete rollback for hasMany and belongsTo relationships:

https://stackoverflow.com/a/27184207/188740

Community
  • 1
  • 1
Johnny Oshika
  • 54,741
  • 40
  • 181
  • 275
0

I like to do the good ol' model.reload() - it'll blow away all changes you haven't synced with your server though.

Joe B
  • 1,261
  • 14
  • 20
  • Late to the party, but here we go: I created an addon that resolves this issue. Just call `rollbackRelationships()` and it will rollback all your relationships. Look at the README for more options. https://www.npmjs.com/package/ember-rollback-relationships – dylanmensaert Apr 20 '18 at 07:48