Re: [Specifications] Actions with explicit target

My apologies everyone for staying gone offline for so long. We had real mess with changing to faster and more reliable broadband in our pretty remote home. I hope from now on we should enjoy stable connection.

I'd like to point a major problem this PR tries to solve, if we look at pseudo code of current use cases:
* [**UC5** Create and add to collection with **POST**](https://github.com/HydraCG/Specifications/blob/0b32ddd0792752e619ff819510557b3cf1316a9f/drafts/use-cases/5.creating-new-event.md#usage)
* [**UC5.1** Create and add to collection with **PUT**](https://github.com/HydraCG/Specifications/blob/0b32ddd0792752e619ff819510557b3cf1316a9f/drafts/use-cases/5.1.creating-event-with-put.md#usage)

Currently client needs to have *prior knowledge* of which one of those server uses and write different code based on that *prior knowledge*. IMO client shouldn't have to do that and same code should handle both of those cases. Separating the semantic *action* which client intends to perform, from *operation* which provides server specific details of how to perform (handle) that action looks like promising approach.

I would propose to focus first on the part of this pull request related to just those two use cases **UC5** & **UC5.1**

While I wanted to avoid getting stuck in details of the pseudo code, now I think that if we want to have same code handling both cases, it might make sense to take a moment to agree on that pseudo code or even take a small detour to try implement in in Heracles.ts

**currently common part of pseud code in UC5 & UC5.1**
```js
var event = {
    "@context": "/api/context.jsonld",
    "@type": "schema:Event",
    "eventName": "My brand new event",
    "eventDescription": "Hope it will work",
    "startDate": "2017-04-19",
    "endDate": "2017-04-19"
};
var client = new HydraClient();
```

[UC5](https://github.com/HydraCG/Specifications/blob/0b32ddd0792752e619ff819510557b3cf1316a9f/drafts/use-cases/5.creating-new-event.md#usage) specific
```js
var operation = client.get("http://example.com")
    .getApiDocumentation()
    .getEntryPoint()
    .getCollection({
      property: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
      object: "http://schema.org/Event"
      })
    .getOperationOfType('http://schema.org/CreateAction');
client.invoke(operation, event);
```

[UC5.1](https://github.com/HydraCG/Specifications/blob/0b32ddd0792752e619ff819510557b3cf1316a9f/drafts/use-cases/5.1.creating-event-with-put.md#usage) specific
```js
var templateVariables = {
    slug: [
        'meeting',
        'with-will'
    ]
};

var memberTemplate = client.get('http://example.com/events').memberTemplate;
var operation = memberTemplate
    .getOperationsOfType('http://schema.org/CreateAction')
    .thatExpect('http://schema.org/Event')
    .first();

const operationWithTargetExpanded = operation.expandTarget(templateVariables);
client.invoke(operationWithTargetExpanded, event);
```

Since in *UC5.1* mapping for IriTemplate includes
```json
{
                "@type": "IriTemplateMapping",
                "variable": "slug",
                "property": "schema:name",
                "required": true
 }
```
and event itself includes value for *eventName* property (mapped in JSON-LD context to *schema:name*), i think pseudo code above doesn't need that `templateVariables` assignment and can just use value from the `event` client intends to create. Actually in current state mapping `slug` to `schema:name` but using some other value than one from the payload seems bit confusing to me. Also if we need value of `slug` different than value of `schema:name` property, *UC5* should also have a way to provide it, which means same code should still work just fine.

Given above we could combine snippets specific to *UC5* and *UC5.1* into something like
```js
const collection = client.get("http://example.com")
    .getApiDocumentation()
    .getEntryPoint()
    .getCollection({
      property: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
      object: "http://schema.org/Event"
      })

const operation = collection.getOperationForAction('http://schema.org/CreateAction')
    .thatExpect('http://schema.org/Event')
    .first();

client.invoke(operationWithTargetExpanded, event);
```

Generic Hydra client (like Herakles.ts) can most likely implement that relying internally on *memberTemplate*, doing some magic under the hood to streamline discovery of operations directly referenced from the collection and those referenced from template which collection references with *memberTemplate*. In my opinion this would take the raw JSON structure of the collection further apart from the interface provided by the client. Taking approach proposed in this PR for me keeps the JSON representation and interface provided by generic hydra client more aligned.

In next days I will regularly respond to all discussions on this PR to have it moving forward before our next telecon!

---

Review status: all files reviewed at latest revision, 6 unresolved discussions.

---



*Comments from [Reviewable](https://reviewable.io:443/reviews/hydracg/specifications/154#-:-L7WdPMiPIIEX6-XGqVD:b6lgmuv)*
<!-- Sent from Reviewable.io -->


-- 
GitHub Notification of comment by elf-pavlik
Please view or discuss this issue at https://github.com/HydraCG/Specifications/pull/154#issuecomment-372860885 using your GitHub account

Received on Wednesday, 14 March 2018 00:06:39 UTC