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:
this.get('store').commit()
is used indoneEditing
of updating a post this jsbin.this.get('model').save()
is used inacceptChanges
of updating a todo this jsbin.
If you turn on Chrome debug and walk into the above two functions, you'll see something similar to below:
Downstream, there is
currentTransaction
ordefaultTransaction
, 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
andflushSavedRecords
, 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'scommit()
.DS.Transaction
s
commit()has a
commitDetails, which is based on xxxTransaction, so
commitDetails` also has all the records of the data. (github)Then DS.Adapter's
commit
andsave
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?