1

Is it possible to clone (deep-copy) a record in Ember Data? I've found answers for pre-1.0beta, but nothing for the recent versions of Ember Data.

This is what I've tried (with little to no success):

  attributesOf: function(record) {
    var attributes = record.get('constructor.attributes')
      , newRecordAttributes = {}

    attributes.forEach(function(attribute) {
      newRecordAttributes[attribute] = record.get(attribute)
    })

    return newRecordAttributes
  }

, cloneSnapshot: function(snapshot) {
    var that = this
      , regions = snapshot.get('regions')
      , networks = snapshot.get('networks')
      , terminals = snapshot.get('terminals')
      , scenario = snapshot.get('scenario')
      , newSnapshot = this.store.createRecord('snapshot', {
                        name: snapshot.get('name')
                      , timestamp: Date.now()
                      , autosave: false
                      , fresh: true
                      })
      , newRegions = regions.map(function(region) {
                       var newRegionObj = that.attributesOf(region)
                       newRegionObj.snapshot = newSnapshot
                       var test = that.store.createRecord('region', newRegionObj)
                       return test
                     })
      , newNetworks = networks.map(function(network) {
                        var newNetworkObj = that.attributesOf(network)
                        newNetworkObj.snapshot = newSnapshot
                        return that.store.createRecord('network', newNetworkObj)
                      })
      , newTerminals = terminals.map(function(terminal) {
                         var newTerminalObj = that.attributesOf(terminal)
                         newTerminalObj.snapshot = newSnapshot
                         newTerminalObj.location = newRegions.filterProperty('name', terminal.get('location.name'))[0]
                         newTerminalObj.network = newNetworks.filterProperty('name', terminal.get('network.name'))[0]
                         return that.store.createRecord('terminal', newTerminalObj)
                       })
    Ember.RSVP.all([newSnapshot, newRegions, newNetworks, newTerminals]).then(function(records) {
      records[0].get('regions').pushObjects(newRegions)
      records[0].get('networks').pushObjects(newNetworks)
      records[0].get('terminals').pushObjects(newTerminals)
    }) // doesn't work
    // newSnapshot.set('regions', newRegions) // doesn't work
    // newSnapshot.set('networks', newNetworks) // doesn't work
    // newSnapshot.set('terminals', newTerminals) // doesn't work
    // newSnapshot.get('regions').pushObjects(newRegions) // doesn't work
    // newSnapshot.get('networks').pushObjects(newNetworks) // doesn't work
    // newSnapshot.get('terminals').pushObjects(newTerminals) // doesn't work
    return newSnapshot
  }

Any way I try it, newSnapshot.get('regions.length') ends up being 0. The same with networks and terminals.

4

1 回答 1

0

Ember Data 似乎不会将DS.belongsTo关系传播给它们的DS.hasMany对应对象,因此我需要将新记录推送到它们相应的多关系中。我的一些关系是用 定义的{ async: true },这需要使用 promise 回调来推送新记录。没有定义的一种关系async,即newTerminalObj.location.get('terminals')要求直接推送记录;使用 promise 回调导致记录永远不会被推送,因为then在没有定义时关系缺少方法async

  attributesOf: function(record) {
    var attributes = record.get('constructor.attributes')
      , newRecordAttributes = {}

    attributes.forEach(function(attribute) {
      newRecordAttributes[attribute] = record.get(attribute)
    })

    return newRecordAttributes
  }

, cloneSnapshot: function(snapshot) {
    var that = this
      , regions = snapshot.get('regions')
      , networks = snapshot.get('networks')
      , terminals = snapshot.get('terminals')
      , scenario = snapshot.get('scenario')
      , newSnapshot = this.store.createRecord('snapshot', {
                        name: snapshot.get('name')
                      , timestamp: Date.now()
                      , autosave: false
                      , fresh: true
                      })
      , newRegions = regions.then(function(array) {
                       return array.map(function(region) {
                         var newRegionObj = that.attributesOf(region)
                         newRegionObj.snapshot = newSnapshot
                         return that.store.createRecord('region', newRegionObj)
                       })
                     })
      , newNetworks = networks.then(function(array) {
                        return array.map(function(network) {
                          var newNetworkObj = that.attributesOf(network)
                          newNetworkObj.snapshot = newSnapshot
                          return that.store.createRecord('network', newNetworkObj)
                        })
                      })
      , newTerminals = Ember.RSVP.all([terminals, newRegions, newNetworks]).then(function(arrays) {
                         return arrays[0].map(function(terminal) {
                           var newTerminalObj = that.attributesOf(terminal)
                           newTerminalObj.snapshot = newSnapshot
                           newTerminalObj.location = arrays[1].filterProperty('name', terminal.get('location.name'))[0]
                           newTerminalObj.network = arrays[2].filterProperty('name', terminal.get('network.name'))[0]
                           var newTerminal = that.store.createRecord('terminal', newTerminalObj)
                           newTerminalObj.location.get('terminals').pushObject(newTerminal)
                           newTerminalObj.network.get('terminals').then(function(array) {
                             array.pushObject(newTerminal)
                           })
                           return newTerminal
                         })
                       })

    Ember.RSVP.all([newSnapshot.get('regions'), newRegions]).then(function(arrays) {
      arrays[0].pushObjects(arrays[1])
    })
    Ember.RSVP.all([newSnapshot.get('networks'), newNetworks]).then(function(arrays) {
      arrays[0].pushObjects(arrays[1])
    })
    Ember.RSVP.all([newSnapshot.get('terminals'), newTerminals]).then(function(arrays) {
      arrays[0].pushObjects(arrays[1])
    })
    return newSnapshot
  }
于 2013-10-10T14:55:26.013 回答