LDflex / Query-Solid

Simple access to data in Solid pods through LDflex expressions
https://solid.github.io/query-ldflex/
MIT License
66 stars 15 forks source link

Add multi-doc example #43

Open michielbdejong opened 4 years ago

michielbdejong commented 4 years ago

The example in https://github.com/solid/query-ldflex/blob/master/demo/profile.js works inside one document. But if a profile only contains the foaf:knows triple, then the objects of those will need to be dereferenced before you can produce a list of first names of someone's friends. With @Vinnl, @james-martin-jd and myself we eventually worked out how to do that, in this chat conversation: https://gitter.im/solid/app-development?at=5d9de406b385bf2cc69f6c8d

Would be good to add an example of that (or maybe even better, a link to a tutorial) to the readme of this repo!

michielbdejong commented 4 years ago

cc @NSeydoux

michielbdejong commented 4 years ago

See also further comments in that gitter conversation from @RubenVerborgh; in general, an app should not know where data lives. So the app would just retrieve each friend's name from "the web".

But having said that, currently in practice the app often does (need to) know, and so if an app wants to retrieve each friend's name from that friend's profile, the code would be something like:

 const friends = [];
 for await (const friend of person.friends) {
   const name = await data[friend].name;
   friends.push(name.value);
 }
michielbdejong commented 4 years ago

Note that a (slightly more cryptic?) alternative to

friends.push(name.value);

there would be

friends.push(`${name}`);

which I think is why you don't see the .value being needed in for instance https://github.com/solid/query-ldflex/blob/master/demo/profile.js#L17 right?

RubenVerborgh commented 4 years ago

why you don't see the .value being needed in for instance https://github.com/solid/query-ldflex/blob/master/demo/profile.js#L17 right?

Exactly; the name variable in the above example will hold an LDflex path, which can be coerced into a string, for instance through string interpolation expressions. Another option is to friends.push(name) and then stringify at a later stage, for instance through friends.join(', '). LDflex paths are proxy objects that you can treat in many ways; as a Promise, as an async interable, as a path, as a string, … Depending on the context, you might want to force them into one or the other. Less cryptic might be name.toString(), which is what the above is eventually doing.

james-martin-jd commented 4 years ago

@RubenVerborgh a coding pattern we've fallen into using is something along the lines of

const myData = await solid.data['subject/path'].predicate;
return myData ? myData.value : null;

So basically in a function (or UI binding object, or React state object, wherever we need to use the value) we check to see if the proxy exists then return the value or an appropriate default value. There may be a better way to handle this, but it works nicely for our purposes, and it might be good to have some extra examples including how to handle null/empty values.

We ran into issues early on since if the predicate or subject doesn't exist, the proxy is null, so the .value blows up.

RubenVerborgh commented 4 years ago

@james-martin-jd Hmm, we probably want something like (await solid.data['subject/path'].predicate).value to give undefined if there are no matches?

james-martin-jd commented 4 years ago

Yes I think that sounds right - if the proxy itself is undefined it throws errors that the root object is undefined, not the .value. But really, I want to know about the value, not the proxy itself.