Opened 11 years ago

Closed 11 years ago

Last modified 11 years ago

#7356 closed defect (fixed)

JsonRestStore prototypes on lazy objects

Reported by: maulin Owned by: Jared Jurkiewicz
Priority: high Milestone: 1.2
Component: DojoX Data Version: 1.1.1
Keywords: JsonRestStore Cc: kzyp@…
Blocked By: Blocking:

Description

Not sure if this is a bug or by intention, but it certainly is a bug for me:

If you have a simple self-referencing JSON, then prototypes work perfectly.

If you have a JSON is loaded first, then a second JSON refers to objects in the first JSON, then protoypes work.

But if you have a JSON that refers to an as yet unloaded entity (which I imaigine is the whole point of lazy $ref'erences) then it first loads the lazy reference into the index. This means that when the item is lazy loaded, the instance is already found in the index (which is a good thing), but the protoype is never applied. So I guess prototypes are not being applied to lazy references in json.ref. The worst part of this is that if I then load the lazy item in its own store, or in any other way, it still does not get the prototype (since json.ref always finds it in its index, and it was initially instantiated without the prototype)

A test case (uses some of my own scaffolding, but you get the idea)

(function() {

var mockItemsService = new medryx.data.mock.MockRestService?(dojo.moduleUrl("medryx.data.tests", "items.json")); var mockRelatedService = new medryx.data.mock.MockRestService?(dojo.moduleUrl("medryx.data.tests", "related.json")); var scaffold = {

setUp:function() {

this.itemsStore = new dojox.data.JsonRestStore?({

service: mockItemsService, target:"/item", schema:{

prototype:{

getFoo:function() {

return this.foo;

}

}

}

});

this.relatedStore = new dojox.data.JsonRestStore?({

service: mockRelatedService, target:"/relative", schema:{

prototype:{

getBar:function() {

return this.bar;

}

}

}

});

}

}

doh.register("LazyPrototypeTests?", [

new doh.AsyncTestCase?("testProtoExistsOnRelatedLazy", function() {

relatedStore.fetch({onComplete:callback})

}, function(items) {

assertTrue(dojo.isFunction(items[0].getBar)); assertTrue(dojo.isFunction(items[0].getBar().getFoo)); FAILS

}, scaffold),

]);

})();

where the data is:

items.json:

[

{

id:"1", foo:"foo", bar:{$ref:"2"}

}, {

id:"2", foo:"foo2", bar:{$ref:"3"}

}, {

id:"3", foo:"foo3", bar:{$ref:"1"}

}

]

related.json:

[

{

id:"1", foo:"foo-rel", bar:{$ref:"/item/2"}

}, {

id:"2", foo:"foo2-rel", bar:{$ref:"/item/3"}

}, {

id:"3", foo:"foo3-rel", bar:{$ref:"/item/1"}

}

]

Attachments (1)

ref.js.patch (2.1 KB) - added by maulin 11 years ago.

Download all attachments as: .zip

Change History (4)

Changed 11 years ago by maulin

Attachment: ref.js.patch added

comment:1 Changed 11 years ago by maulin

I have attached a patch to ref that fixes this. basically i extracted your proto code to a local utility function and then invoke it in two places -- once where it originally was, and again near line 110 where you were adding the straight json val (property value) of "it" to the index, to be sure the prototype is created first.

This fixes the above, as well as allows arrays with lazy references to use protoypes without any problems.

comment:2 Changed 11 years ago by Kris Zyp

Resolution: fixed
Status: newclosed

(In [14688]) fixes #7356

comment:3 Changed 11 years ago by Kris Zyp

Maulin, thanks for the bug report and patch, great work. I patched it a little differently, calling walk with the lazy object instead of the creating findProto function. This should actually be more correct for lazy objects as well (as they may include properties they need processing, like other lazy properties). Let me know (reopen the ticket) if this doesn't fix your problem.

Note: See TracTickets for help on using tickets.