-
Notifications
You must be signed in to change notification settings - Fork 422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
can.Model.findAll loads lists and mixes it with previously loaded #245
Conversation
Looks like a bug in |
Do you mean Observe.List.protorype.replace? Why it is used while creating new model/list from new data arrived? |
Your Fiddle uses it in line 38. This is where I think the problem is. |
No, I've updated fiddle and removed replace, I just rerender view now with new list, it seems that the problem in findAll. |
Ok I see what you mean. Problem is, that this is how the model store works. If you explicitly set the attribute to can.Model.model = function( attributes ) {
if ( ! attributes ) {
return;
}
if ( attributes instanceof this ) {
attributes = attributes.serialize();
}
var id = attributes[ this.id ],
model = id && this.store[id] ? this.store[id].attr(attributes, true) : new this( attributes );
if(this._reqs){
this.store[attributes[this.id]] = model;
}
return model;
} Should do the trick. Please give it a quick try for your problem. If that works I'd propose adding a static |
Yes, thank you, it seems that it does. I just doesn't understand what is the logic behind mixing behind model store that made it to look at previously loaded instance? Can you explain? |
The idea is: Models are uniquely identified by ID. So if you get model data with the same id Can assumes that it is the same model and will update the store. When your model data is live-bound (or listening to Observe changes any other way) somewhere (and models instances in the store always are, otherwise they will be removed from it) all your views and other listeners will be notified if the model is re-loaded from the server and attributes are updated. You also want all lists to remove a model if it is destroyed etc. |
The idea is: Models are uniquely identified by ID. So if you get model data with the same id Can assumes that it is the same model and will update the store. Ok that is very good point. I just don't undertand how nested lists where updated that caused the issue? My particular case: I load from server a model, model contains nested list of items. Then I decide to synchronize model state with server, I load again the same model (with the same id). Between this two syncs new item was added on server to DB to the list. So I get new model with updated list that contains one new item. Items in the list say may have or have not field called 'finished', new item doesn't have it, but after loading can.Model adds this field ("finished") to new item and takes the value from first item of the list that where loaded previously. I hope I made my self clear. Can you explain it? |
I'm not totally clear. A demo fiddle might help a lot. Sent from my iPhone On Jan 22, 2013, at 11:05 PM, Alex Osh notifications@github.com wrote:
|
This are actually two issues (part of which I think the http://jsfiddle.net/qYdwR/645/ Fiddle demonstrates): The first one @moschel just addressed in #251: Nested arrays should never be merged. Otherwise you have weird things like this happening: var state = new can.Observe({
arr: ["a", "b"]
});
state.attr({
arr: ["c"]
});
// state => {arr: ["c", "b"]} The second one is, that var MyModel = can.Model({}),
model = MyModel.model({
id: 0,
name: 'Test',
index: 1
});
// After e.g. reloading
model = MyModel.model({
id: 0,
name: 'Test'
});
model.attr('index') // -> still 1, but should be undefined I think it would make sense to add a |
Yes, that is the point, as I've said new list was "mixed" with previously loaded, wrong verb -) it was actually merged with it. |
Ok, as a non inversive fix for 1.1.4 I attached a pull request that adds a var Todo = can.Model({
findAll : 'GET /todos',
findOne : 'GET /todos/{id}',
create : 'POST /todos',
update : 'PUT /todos/{id}',
destroy : 'DELETE /todos/{id}',
removeAttr: true
}, {}); Which will cause any request and |
* be merged. Setting `removeAttr` to `true` will result in model attributes like | ||
* | ||
* { id: 1, name: 'Really do dishes' } | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good docs, but might also want to mention the effect this has on arrays (causes them to be replaced instead of "merged").
I can help with this.
added removeAttr property for can.Model to prevent attribute merging
http://jsfiddle.net/qYdwR/643/
First, fiddle loads and renders 5 todos with set attribute index (from 0.. 5)
Then click "Load New Todos" - with another fixture (that doesn't provide index attributes) we load new 10 todos, and render new list, so I would expect that: ALL of new todos would have index attribute undefined - but they do not, todos 1 to 4 have index attribute from old list.