2013-03-02 13 views
11

mam dwa modele:Usuń powiązanych model z Ember-danych

App.User = DS.Model.create({ 
    comments: DS.hasMany('App.Comment') 
}); 

App.Comment = DS.Model.create({ 
    user: DS.belongsTo('App.User') 
}); 

Gdy użytkownik zostanie usunięty, ale także usunie wszystkie swoje uwagi na backend, więc należy usunąć je z tożsamością po stronie klienta mapa.

Zamawiam wszystkie komentarze w systemie z innego miejsca, więc po usunięciu użytkownika spowodowałoby to awarię.

Czy istnieje sposób określenia tego rodzaju zależności od powiązania? Dzięki!

Odpowiedz

9

Używam mixin, gdy chcę zaimplementować to zachowanie. Moje modele są zdefiniowane następująco:

App.Post = DS.Model.extend(App.DeletesDependentRelationships, { 
    dependentRelationships: ['comments'], 

    comments: DS.hasMany('App.Comment'), 
    author: DS.belongsTo('App.User') 
}); 

App.User = DS.Model.extend(); 

App.Comment = DS.Model.extend({ 
    post: DS.belongsTo('App.Post') 
}); 

mixin sama:

App.DeletesDependentRelationships = Ember.Mixin.create({ 

    // an array of relationship names to delete 
    dependentRelationships: null, 

    // set to 'delete' or 'unload' depending on whether or not you want 
    // to actually send the deletions to the server 
    deleteMethod: 'unload', 

    deleteRecord: function() { 
     var transaction = this.get('store').transaction(); 
     transaction.add(this); 
     this.deleteDependentRelationships(transaction); 
     this._super(); 
    }, 

    deleteDependentRelationships: function(transaction) { 
     var self = this; 
     var klass = Ember.get(this.constructor.toString()); 
     var fields = Ember.get(klass, 'fields'); 

     this.get('dependentRelationships').forEach(function(name) { 
      var relationshipType = fields.get(name); 
      switch(relationshipType) { 
       case 'belongsTo': return self.deleteBelongsToRelationship(name, transaction); 
       case 'hasMany': return self.deleteHasManyRelationship(name, transaction); 
      } 
     }); 
    }, 

    deleteBelongsToRelationship: function(name, transaction) { 
     var record = this.get(name); 
     if (record) this.deleteOrUnloadRecord(record, transaction); 
    }, 

    deleteHasManyRelationship: function(key, transaction) { 
     var self = this; 

     // deleting from a RecordArray doesn't play well with forEach, 
     // so convert to a normal array first 
     this.get(key).toArray().forEach(function(record) { 
      self.deleteOrUnloadRecord(record, transaction); 
     }); 
    }, 

    deleteOrUnloadRecord: function(record, transaction) { 
     var deleteMethod = this.get('deleteMethod'); 
     if (deleteMethod === 'delete') { 
      transaction.add(record); 
      record.deleteRecord(); 
     } 
     else if (deleteMethod === 'unload') { 
      var store = this.get('store'); 
      store.unloadRecord(record); 
     } 
    } 
}); 

pamiętać, że można określić poprzez deleteMethod, czy chcesz wysłać DELETE żądań do API. Jeśli twój back-end jest skonfigurowany tak, aby automatycznie usuwał zależne rekordy, wtedy będziesz chciał użyć wartości domyślnej.

Oto jsfiddle, który pokazuje go w akcji.

+0

Hej, to wygląda bardzo dobrze! Chociaż myślę, że 'ember-data' powinien wspierać coś takiego w rdzeniu. Dzięki za tak szczegółowe wyjaśnienie, koleś! – josepjaume

+0

Zgadzam się. W Ember Data brakuje kilku kluczowych funkcji, ale wciąż jest bardzo młody i bardzo szybko się rozwija. – ahmacleod

+1

Dane Ember nie obsługują już transakcji, więc powyższy kod będzie musiał zostać zmieniony, aby działał z ostatnimi kompilacjami. – ahmacleod

3

Szybkie i-brudny sposób byłoby dodać następujące modelu użytkownika

destroyRecord: -> 
    @get('comments').invoke('unloadRecord') 
    @_super() 
0

I dostosowany Odpowiedź @ahmacleod pracować ember-cli 2.13.1 i ember-data 2.13.0. Miałem problem z zagnieżdżonymi relacjami oraz faktem, że po usunięciu obiektu z bazy danych jego identyfikator został ponownie użyty. Doprowadziło to do konfliktów z resztkami w modelu danych ember.

import Ember from 'ember'; 

export default Ember.Mixin.create({ 
    dependentRelationships: null, 

    destroyRecord: function() { 
     this.deleteDependentRelationships(); 

     return this._super() 
     .then(function (model) { 
      model.unloadRecord(); 

      return model; 
     }); 
    }, 

    unloadRecord: function() { 
     this.deleteDependentRelationships(); 

     this._super(); 
    }, 

    deleteDependentRelationships: function() { 
     var self = this; 
     var fields = Ember.get(this.constructor, 'fields'); 

     this.get('dependentRelationships').forEach(function(name) { 
      self.deleteRelationship(name); 
     }); 
    }, 

    deleteRelationship (name) { 
     var self = this; 
     self.get(name).then(function (records) { 
      if (!records) { 
       return; 
      } 

      var reset = []; 
      if (!Ember.isArray(records)) { 
       records = [records]; 
       reset = null; 
      } 

      records.forEach(function(record) { 
       if (record) { 
        record.unloadRecord(); 
       } 
      }); 

      self.set(name, reset); 
     }); 
    }, 
}); 

końcu, było ustawić związek z [] (hasMany) lub null (belongsTo). Inaczej bym napotkasz następujący komunikat o błędzie:

Assertion Failed: You cannot update the id index of an InternalModel once set. Attempted to update <id>.

Może to jest pomocne dla kogoś innego.