PDA

View Full Version : [CLOSED] Stores with Model with Sync issue



wizkid
19 Mar 2011, 8:57 AM
I am not 100% sure if this is a bug or not. But something is not working the way I would expect it.

I want to send a list of JSON to a model in a store:


[
{
"LoginUserId": "[email protected]",
"FirstName": "UserFirst",
"LastName": "UserLast",
},
{
"LoginUserId": "[email protected]",
"FirstName": "Joe",
"LastName": "Dole",
}
]
I do mystore.load and it works great. I can see the items in my list.

Then I do this:


mystore.load({
scope: this,
callback: function (records, operation, success) {
console.log("Got Editable List");

records[0].set('FirstName', 'work');
records[0].set('LastName', 'please');

records[1].set('FirstName', 'work2');
records[1].set('LastName', 'please2');
}
});
The set(...) above work fine.

Then I do a mystore.sync(..)

Now this is where my problem lies. I think the default case of sending a two POSTs sending each change item in the list is fine. But what I want is to have it sent all in one go. This worked in PR3 (sorta) sending a JSON array back to my server. The odd thing though is it did a post of my whole list and then a PUT... That was all PR3, and I guess there were bugs in that area. I will mention I did not ADD anything new to my model store. Just a get, then some sets and then a sync.

Anyway, so I started digging around to see if there was a way to override this behavior. This is where I think the bug is.

In my store I set this batchUpdateMode: 'complete'

From the documentation it sounded exactly what I wanted. Except when I do a .sync(..) it does a POST and then a PUT... WEIRD! Just like PR3 except the POST does not have an array of my updated list. I think this is a bug. I don't think you would want a PUT in this case, plus the POST is missing my array. So, I don't know if in PR3 it was supposed to send the array back to the server... But I would like it to!

Thoughts?

evant
19 Mar 2011, 4:30 PM
Say you're updating a record, wouldn't the request look something like:



PUT /users/1


So why are you sending more than 1 record?

wizkid
20 Mar 2011, 1:28 PM
I am fairly sure something is going wrong... Consider this below:



var storeUsers = new Ext.data.Store({ model: 'UserListWritable'})

Then I do a load:


function getEditList() {
storeUsers.load({
scope: this,
callback: function (records, operation, success) {
console.log("Got Editable List");

records[0].set('FirstName', 'Slouch');
records[0].set('LastName', 'Man');

records[1].set('FirstName', 'Test');
records[1].set('LastName', 'theName');
}
});

Note: I ONLY changed two records, above, after the load.

This is the JSON I get back from the server and it loads it correctly:


[
{
"LoginUserId": "[email protected]",
"FirstName": "User1",
"LastName": "User1 Last",
"IsNew": false,
"IsDeleted": false,
"IsDirty": false
},
{
"LoginUserId": "[email protected]",
"FirstName": "Slirpy",
"LastName": "Dole",
"IsNew": false,
"IsDeleted": false,
"IsDirty": false
},
{
"LoginUserId": "[email protected]",
"FirstName": "Really",
"LastName": "Sweet",
"IsNew": false,
"IsDeleted": false,
"IsDirty": false
}
]
Then I do a sync(...) on the store.... I get three POSTs and two PUTs

POST 1



{
"LoginUserId": "[email protected]",
"FirstName": "Slouch",
"LastName": "Man",
"IsNew": false,
"IsDeleted": false,
"IsDirty": true
}
POST 2


{
"LoginUserId": "[email protected]",
"FirstName": "Test",
"LastName": "theName",
"IsNew": false,
"IsDeleted": false,
"IsDirty": true
}
POST 3


{
"LoginUserId": "[email protected]",
"FirstName": "Really",
"LastName": "Sweet",
"IsNew": false,
"IsDeleted": false,
"IsDirty": false
}
PUT 1


{
"LoginUserId": "[email protected]",
"FirstName": "Slouch",
"LastName": "Man",
"IsNew": false,
"IsDeleted": false,
"IsDirty": true
}
PUT 2


{
"LoginUserId": "[email protected]",
"FirstName": "Test",
"LastName": "theName",
"IsNew": false,
"IsDeleted": false,
"IsDirty": true
}
So why am I getting three POSTs (they have the updated data sent to the server as you can see) and two PUTs (only two because I only changed data on two)?

It should be one or the other but not BOTH. I can see it just doing two PUTs for changed data. I don't know why you would want three POSTs and two PUTs when only two items changed! To me this is a bug.

Remember I am doing:


var storeUsers = new Ext.data.Store({ model: 'UserListWritable'})
storeUsers.setProxy(new Ext.data.RestProxy({
url: '/Home/EditableUserListDataPortal/',
reader:{
type: 'json'
},
writer:{
type: 'json'
} }));
So the way it should work is Two POSTs or Two PUTs? Don't you agree?

Now in some cases this is the way you would want it to work. In my case I have some small lists that I don't want the overhead of having seperate calls to my web server. I would rather have ONE call that contained at least both changes in one POST. I would be fine with All data being sent up to the server in one JSON array (changed or unchanged). Also I would like it to be kept into JSON Array form when it's being sent in one list. Regardless of if it's one item or two that has changed. If it comes from the server in an Array it should go back to the server as an array if I have it set to go "all in one post"... It should preserve that contract of what came down.

In Preview 3 it would send a Array of all data, unchanged or changed in one giant POST (I want this in some cases). Then it would start doing PUTs... I figured that was a bug and it would be fixed in the next PR. Well, now what I am seeing is multiple POSts and multiple PUTs... Once it's fixed I think the default of two PUTs OR two POSts are fine.

But I want to send the whole list back and thought batchUpdateMode: 'complete' would do that for me.

But it does the same thing. I guess what is batchUpdateMode supposed to do?

To sum things up first the multiple POSTs and PUTs seems like a bug?

Second is there a way to make changes to a store and do a sync(..) and get data send back like this in this format always (it would be ok not to send unchanged data in this case):


[
{
"LoginUserId": "[email protected]",
"FirstName": "Slouch",
"LastName": "Man",
"IsNew": false,
"IsDeleted": false,
"IsDirty": true
},
{
"LoginUserId": "[email protected]",
"FirstName": "Test",
"LastName": "theName",
"IsNew": false,
"IsDeleted": false,
"IsDirty": true
},
{
"LoginUserId": "[email protected]",
"FirstName": "Really",
"LastName": "Sweet",
"IsNew": false,
"IsDeleted": false,
"IsDirty": false
}
]

evant
20 Mar 2011, 3:05 PM
You need to specify an id. The request will be sent like:



PUT
/Foo/Yourpage/1


In this case, you need to specify the idProperty on the model, if you aren't doing so.

wizkid
20 Mar 2011, 5:40 PM
Ahhh, thanks evant! It works. I now just get two PUTs with my store and my list. I withdraw, at least partially, my bug report! :D

I have a few suggestions / comments / enhancements.

First I would think if the idProperty is required, in this case, then it would be nice to have an exception thrown! I did not realize it, and in my case it was doing two PUTs and three POSTs... When would you ever want that to happen?!

Second, the desired functionality of doing one POST with an array of changed data, in a store, still is outstanding. Like I said, rather intentional or not, it sorta worked that way in PR3.

I think there would be various cases where this kind of functionality would be helpful. For example in my Server, in allot of cases, it would be nice to have the same data structure coming in, as going out. So, if an Array is going out, an array comes back in. This is nice architecturally because on my server I have automatic serialization and deserialization, and in some cases I would like to keep the contract the same.

I do agree having separate PUT calls should be the default. I just liked the way (intentional or not) it worked in PR3.

Is there any way now to do this? Also, what does "batchUpdateMode" do on the store?

Thanks for your help!

steffenk
21 Mar 2011, 12:48 AM
changing many records in one call still is an important way to go.
Single requests are lightweight if you are in small demo context. if you are in a BE application that need proper auth also for ajax requests, each request is expensive, and there must be a way to do most things bundled.
This is the case in Ext3 with store.commit().