Open plexus opened 9 years ago
if i understand the Q here...
the top link SHOULD always be the collection link (collection.href
). that is because rendering a "single resource" in Cj is actually a Cj collection with a single item
the self link SHOULD always appear in the links array (collection.links[{rel:"self",...},...]
).
does that clarify things?
That does help somewhat. In Yaks we do make a distinction between serializing a single object or serializing a collection. In either case we first build up an intermediate "resource object", and then output formats (e.g. CJ) can work with that to the best of their ability.
So suppose I'm outputting a single object, and I have configured both a self and a collection link on it.
Yaks::Resource.new(
links: [
Yaks::Link.new(rel: :self, href: "/foo/15"),
Yaks::Link.new(rel: :collection, href: "/foo")
]
)
this could be rendered with
"href": "/foo",
"links": [{"rel": "self", "href": "/foo/15"}]
whereas a collection
Yaks::CollectionResource.new(
links: [
Yaks::Link.new(rel: :self, href: "/foo")
]
)
would be
"href": "/foo",
"links": [{"rel": "self", "href": "/foo"}]
Does that look good?
What if a single resource does not have a collection URI? Should we consider it an error to try to output that to Collection+JSON? Or do we omit the "href"? (same for a collection without a self link).
first, the examples for single and collection look good to me. this is the same output i produce in my own examples.
also, it is valid for a representation to not have a collection.href
property -- this happens when the collection is read-only. you would still emit a "self" link in the collection.links[]
array, tho. this is true whether you are rendering a "single-item" collection (your Yaks::Resource
) or a "multi-item" collection (your Yaks::CollectionResource
).
make sense?
Yeah that makes sense. Not sure how we would expose that distinction in our existing API, but I understand the rationale.
cool. feel free to ping me for these kinds of clarification -- it reminds me that the Cj docs are lacking and working through this w/ you helps me quite a bit.
i understand about the challenge of supporting all these details -- esp. across media type designs. i really love the work you're doing here.
I'll have a look at this and the full discussion tonight. I'm into daddy mode at the moment!
On Friday, May 8, 2015, Mike Amundsen notifications@github.com wrote:
first, the examples for single and collection look good to me. this is the same output i produce in my own examples.
also, it is valid for a representation to not have a collection.href property -- this happens when the collection is read-only. you would still emit a "self" link in the collection.links[] array, tho. this is true whether you are rendering a "single-item" collection (your Yaks::Resource) or a "multi-item" collection (your Yaks::CollectionResource).
make sense?
— Reply to this email directly or view it on GitHub https://github.com/plexus/yaks/issues/87#issuecomment-100275423.
@carlesjove
thanks. hopefully, i've articulated the media type details well. you may need to scan the actual implementation details to make sure i've not missed something very imp. regarding Yaks itself.
BTW - was great to spend time w/ you this week in Barcelona for APIDays, thanks.
Well, this whole issue is really tricky, because it can be dealt in many ways. The thing here is that Cj isn't very imperative (even when it's very structured), so a bunch of responses can be valid Cj.
For the situation at hand, this one example is not to passing:
{
"collection": {
"version": "1.0",
"href": "http://www.youtypeitwepostit.com/api/",
"items": []
The reason is because a CollectionMapper
that sets a self
link expects a links
object:
class CollectionMapper < Yaks::CollectionMapper
link :self, 'http://www.youtypeitwepostit.com/api/'
{
"collection": {
"version": "1.0",
"href": "http://www.youtypeitwepostit.com/api/",
"links": [
{"href": "http://www.youtypeitwepostit.com/api/", "rel": "self"}
]
"items": []
I think both responses are valid Cj, so we can either:
If we look at another shared example, the Plants collection, we're expecting the second case:
{
"collection": {
"version": "1.0",
"href": "http://api.example.com/plants",
"items": [...],
"links": [
{ "href": "http://api.example.com/plants", "rel": "self" },
{ "href": "http://api.example.com/doc/plant_collection", "rel": "profile" }
]
}
}
So well, why not leave it as it is, for now, and just change the expectation? That's consistent with what we are already expecting for the Plans collection and implies zero refactoring.
Sure, we can leave everything as is, or we can make it better :) The current implementation will render a self
link at the top level under "links"
, but will skip self links in lower levels. That's already inconsistent.
Also, while what we generate is structurally valid CJ, it's not always semantically valid. When rendering a singular resource, its self
link should not be used to populate "href"
, because "href"
is reserved for the URL of the collection.
I've been thinking we could add metadata to links to differentiate between links that are simply used as identifiers, and others that can actually be looked up. I'm just not sure what to call it. resolvable
or dereferentiable
both seem a bit wordy :)
class FooMapper < Yaks::Mapper
link :self, '/api/foo', resolvable: false # indicates that GET /api/foo will *not* work
If the link to the collection is not "resolvable" it should not be used as collection.href
yes, i'd like to take best advantage of the library here and improve as much as possible.
the collection.href
property is always a URL (locator, resolvable), not a URI (identifier, not-always-resolvable). it appears in responses to tell clients which URL is valid for POST-ing a new item to the collection. for this reason it SHOULD always appear in responses. the only exception is when the collection is read-only.
to be clear the self
link indicates the URL of the current response and, while not a REQUIRED element, it MAY appear in the collection.links
array. As a rule, i always include the self
link in that array. it would be absolutely fine if Yaks always emitted a self
URL in the collection.links
array.
It seems we were having some issues with acceptance tests not actually working as intended. I'm working on a PR that fixes that. It seems we had some CJ behavior that's in conflict with some of the acceptance examples but that wasn't caught before, and that I think we have to revisit.
The question is how to treat "self" links. CJ has a generic "links" collection on each resource, but also a "href". At the moment we render a self link at the top level as a generic self link, and at lower levels as href. I think both of these are wrong.
@mamund clarifies here: https://groups.google.com/d/msg/collectionjson/RHcw72kHUno/hzF3WSbn-ZsJ
In Collection+JSON a singular resource is represented as a collection of one. So the way I interpret this is: If we're rendering a "real" collection (a
Yaks::CollectionResource
), then render a self link as "href", and not under "links". If we render a singular resource (Yaks::Resource
), render it as a self link under "links", and not as "href".Does that make sense? @carlesjove @mamund any input you can give on this? Thanks!