1
votes

Premise: My question is based on my research of Ember-data, which may or may not be correct. So please correct me if I have any misunderstanding. The examples are running with the latest ember as of July 2, 2013.

To edit a record of my model, just 1 record, you need to call this.get('store').commit() or this.get('model').save(). However, downstream of either of these functions actually have to update all of the records of the model, even those left untouched. So this is quite inefficient, especially if the model has numerous records.

What's the best way to update one and only one record when I'm saving the edits of one record?

UPDATE: this problem only occurs for the local-storage-adapter, not the RESTAdapter.

UPDATE #2: I did have a huge misunderstanding. Everything is okay, save() and commit() both update just 1 record, I've been fooled by local storage adapter _saveData's JSON.stringify(this._data) which printed out all records. I assumed that whatever it printed out was the data that is changed, but turns out in _saveData's callers the records in updateRecords and _didSaveRecords were just the single record I was changing. The statements below about different objects containing "all records of the model" can no longer be duplicated. I guess I misread the debugging information.
It makes sense because _saveData uses localstorage, which currently can only setItem for an entire object, which in my case is the model containing all the records. Since localstorage can't update individual entries of that object, the JSON must contain all the records.


Details:

Running Examples:

If you turn on Chrome debug and walk into the above two functions, you'll see something similar to below:

  1. Downstream, there is currentTransaction or defaultTransaction, and both have all records of the model inside.

    In the case of get('store').commit(), it eventually calls DS.Store's commit, which in turn calls: (see github)

    get(this, 'defaultTransaction').commit();
    

    In the case of case of get('model').save(), it eventualy calls DS.Store's scheduleSave and flushSavedRecords, which call: (see github)

    get(this, 'currentTransaction').add(record);
    get(this, 'currentTransaction').commit();
    

    Note at the end a commit() is called on xxxTransaction, this is DS.Transaction's commit().

  2. DS.Transactionscommit()has acommitDetails, which is based on xxxTransaction, socommitDetails` also has all the records of the data. (github)

  3. Then DS.Adapter's commit and save are called and indeed every single record is updated (github):

    this.groupByType(commitDetails.updated).forEach(function(type, set) {
       this.updateRecords(store, type, filter(set));
    }, this);
    

    (minor side note/question: when was commitDetails set to "updated"?)

I know that DS.Adapter can be customized, but clearly the problem of saving more than one data (i.e. all of the model entries) are set from DS.Store's commitDefaultTransaction and currentTransaction.

Somehow I feel it would be a bad idea to tinker with DS.Store or anything upstream of DS.Adapter, like making my own version of save() and commit(). Basically I am reluctant to customize anything I'm told not to, since there might be ugly side effects.

So what should I do if I want to use Ember data but can only afford to update one record only at a time?

1

1 Answers

1
votes

You can create a new transaction just for managing that record, using transaction() method of the store. This transaction has the same api as the defaultTransaction.

var transaction = this.get('store').transaction();
transaction.add(model)
transaction.commit();

Committing this transaction won't affect other changes. See this blog post for further ideas.