Add support for hydra:Link
Closed this issue · 8 comments
I'm submitting a
- bug report.
- feature request.
Discussion
From slack thread:
hydra:Link is precisely used to describe properties which will contain dereferenceable URLs. And it is the only way any client can know existence of dereferenceable URLs. So I think hydrus should only use URLs for nested object when that field(property) is described as a hydra:Link. I should have worked in this direction when I implemented "segregation of nested objects", from what I believe the right approach was to change "DroneState" from "vocab:State" to a hydra:Link and add support in hydrus to handle both of these approaches, by adding the nested resource itself when "vocab:State" is used and adding a URL to State when hydra:Link is used in the API Doc.
Chris: how then do we ensure that the link is for the correct type of object?
The client will look at APIDoc, which will contain the definition of that Link property, which will include the range of the link, which can be used by clients to know which type of resource is represented by that link.
On hydrus side, if I am not missing anything, as of now hydrus only do such type checks for properties which are defined as a class in APIDoc(e.g. vocab:State
) and it is done while inserting such nested objects. We can maintain that functionality intact with hydra:Link
too. When hydra:Link
is used, the client will use a link to the nested object instead of putting the whole object in the request body of the parent object(as of now such resources are directly nested in the parent object's body so hydrus can check that the @type
attribute matches what is described in the APIDoc and thus type checking is done. It will require some modifications to handle type checking of nested-object-properties defined with the help of hydra:Link
.). When hydra:Link
is used and the client provides a link to the nested objects instead of the whole object, hydrus will extract the path
from the URL and find collection or class matching that path, then it can do the direct type checking.
For example, if DroneState
is defined with help of hydra:Link
having vocab:State
as range(1), when hydrus gets a put request for a new drone object, the object will look something like this
{
"@type": "Drone",
...
"DroneState": "/api/StateCollection/id"
}
From link("api/StateCollection/id"), hydrus will extract StateCollection
as path
, and look into APIDoc to find collection with this path
(@id
) and then get class_type, then it can match it with the range defined in the APIDoc as metioned above(1).
Do you want to work on this issue?
Yes
When hydra:Link is used, the client will use a link to the nested object instead of putting the whole object in the request body of the parent object(as of now such resources are directly nested in the parent object's body so hydrus can check that the @type attribute matches what is described in the APIDoc and thus type checking is done. It will require some modifications to handle type checking of nested-object-properties defined with the help of hydra:Link.)
@vddesai1871 Correct me if I'm wrong but if the client is going to provide a link to the nested object that means that the client first need to create the nested object instance in hydrus and then use that object's id as a link to create the object.
If yes, then why not keep the object creation mechanism as it is i.e the client will provide the nested object in the request body itself (like it does now). We just change the internal representation in hydrus i.e how the object will be represented once it the request is parsed and the object is stored.
What I'm proposing is -
- We keep the item creation as it is i.e the client will provide the entire object in request body, hydrus will detect hydra:link type and create a separate object instance for that object and use its id to create the link that will be stored.
P.S.: Please ignore this is all of this has already been discussed.
We haven't discussed this particular topic, but I think it's better to only use the link instead of the whole object while insert/update. For example, take a comment resource with a link to the issue resource, In almost all cases issue will be created before insertion of any comment, means no extra insertion happens while creation of a comment, so why send the whole issue object on the creation of a comment? (we just need the id of the resource through the link to create a new triple to add this new relation.) Same applies to every update on the comment resource.
We keep the item creation as it is i.e the client will provide the entire object in request body, hydrus will detect hydra:link type and create a separate object instance for that object and use its id to create the link that will be stored.
hydrus might end up creating a new issue on insertion of every comment, to avoid that I'll have to add mechanism to see if the nested_resource has an @id
and if it is valid, then just use that
@id to create a triple
, which I am already doing now.
But there might be a case for creation of nested_resource with every creation of the parent_object in that case Api Designer can define such relation with non-link nested object(e.g. vocab:State
), insertion of such object follows the procedure you mentioned but it returns a nested object(in the same response) instead of a link.
For example, take a comment resource with a link to the issue resource, In almost all cases issue will be created before insertion of any comment, means no extra insertion happens while creation of a comment, so why send the whole issue object on the creation of a comment? (we just need the id of the resource through the link to create a new triple to add this new relation.) Same applies to every update on the comment resource.
I was asking about the instance where each object instance will have a separate nested object, for example, consider the drone example. Each drone has a drone state.
But there might be a case for creation of nested_resource with every creation of the parent_object in that case Api Designer can define such relation with non-link nested object(e.g. vocab:State), insertion of such object follows the procedure you mentioned but it returns a nested object(in the same response) instead of a link.
So we're not using hydra:link in this scenario, any particular reason?
So we're not using hydra:link in this scenario, any particular reason?
We can also use hydra:link and the approach I mentioned above(nested resource will have a separate endpoint, nested_object will be added only through that), but if someone wants to add the nested_object in the same request than he can't do it with hydra:Link.
When we define a predicate as a hydra:Link
predicate, then we can't assume it will contain something else than a link.
okay, makes sense!
Probably we want HydraLink properties to appear only in GET operations?
Probably we want HydraLink properties to appear only in GET operations?
You're right, links will mostly be displayed in GET operations but this issue is related to the way any API creator will define those links when writing the APIDoc using doc_writer.