liberator

ordnungswidrig 2017-04-04T15:53:02.992488Z

This should work: ((resource “hello-world”) {:request-method :get})

ordnungswidrig 2017-04-04T15:53:29.005701Z

Parametrized resources accept the parameters as function arguments and return an actual handler function.

ordnungswidrig 2017-04-04T15:54:40.039746Z

@ejelome ^^ got you an answer. see above.

bostonaholic 2017-04-04T16:03:07.286714Z

@ejelome 2 things. 1) I think testing defresource directly isn’t valuable. My opinion. defresource is already tested within liberator’s source code. 2) If you still feel like you need to test it, just check out liberator’s test suite on how to do it. https://github.com/clojure-liberator/liberator/blob/master/test/test_defresource.clj

2017-04-04T16:20:12.741777Z

probably an e2e test would be better in these cases

ordnungswidrig 2017-04-04T16:44:44.384181Z

I had the impression that the OP simply wanted to test his resource and struggled with how parameters would be passed. That's a valid and proper test. OP might have simplified for the sake of example I guess.

ordnungswidrig 2017-04-04T19:05:20.060356Z

Regarding the detailed messages: the server returns an error if the username was already taken. But this could be the case when a user tried to register the first time or when he/she wants to change the username.

ordnungswidrig 2017-04-04T19:06:03.078560Z

For the server it’s the same operation, e.g. PUT /users/ordnungswidrig/name but you want to show different error messages to the user.

ordnungswidrig 2017-04-04T19:06:47.096696Z

I had good experience with a server returning a keyword for the error, e.g. :username-conflict and the client uses a dictionary to lookup an appropriate error message depending on the interaction.

urzds 2017-04-04T19:08:58.150178Z

That's kind of what I am trying to do.

urzds 2017-04-04T19:09:05.152799Z

Actually exactly

urzds 2017-04-04T19:10:25.185109Z

But I want to check all errors that leave Liberator to adhere to a schema. And as a bonus, I would like to make it easy to find the source of :username-conflict, i.e. where in the code it was emitted.

ordnungswidrig 2017-04-04T19:11:38.215891Z

there’s grep for that 🙂

urzds 2017-04-04T19:11:51.221203Z

(I'm also passing all non-error data through functions in :handle-ok, to make sure they also conform to the spec.)

urzds 2017-04-04T19:13:14.254577Z

Hm, I guess I could pass :error/username-conflict and just check whether the namespace is error, to guarantee that the grepping will not become too difficult...

ordnungswidrig 2017-04-04T19:13:47.268571Z

yes, namespaced keywords is the way to go

urzds 2017-04-04T19:13:54.271414Z

How are people with really large code bases and different teams working on API and UI doing this? I.e. they have to pass around some kind of documentation...

ordnungswidrig 2017-04-04T19:18:49.389518Z

well, my personal take on this is to stick with the ideas behind REST. One important constraint is that the only documentation is the description of the media types of the resources. This includes the semantics, error cases etc.

urzds 2017-04-04T19:19:06.396432Z

On another topic: @ordnungswidrig Do you have an answer to https://github.com/clojure-liberator/liberator/issues/237#issuecomment-287816541 ? I.e. how to do API documentation with Liberator without Swagger?

ordnungswidrig 2017-04-04T19:19:09.397237Z

That must be sufficient for a well formed user facing client to reason about the system.

ordnungswidrig 2017-04-04T19:19:31.406398Z

I actually commented on that ticket: https://github.com/clojure-liberator/liberator/issues/237#issuecomment-287810782

ordnungswidrig 2017-04-04T19:19:48.413053Z

Oh you meant that example? No I did not came up with one.

ordnungswidrig 2017-04-04T19:20:45.436120Z

This very much depends on the actual usecase, but people nowadays use HAL, Collection+JSON etc. as the underlying media types and there is documentation tooling support for these.

urzds 2017-04-04T19:20:46.436537Z

My knowledge of the terms you used was also too small to fully grasp what you propose as an alternative.

ordnungswidrig 2017-04-04T19:20:55.439785Z

😉

ordnungswidrig 2017-04-04T19:22:20.472706Z

So in recent projects we used application/edn and clojure.spec specification for the interop. The resources linked to each other and the links used a well defined set of relations, e.g. “child”, “parent”, “authorization”

urzds 2017-04-04T19:22:28.475911Z

media type, hypermedia, resource deployment (you refer to (defresource)?), the relation delete, again media types, ...

ordnungswidrig 2017-04-04T19:23:09.491455Z

HAL http://stateless.co/hal_specification.html might be a good start on the ideas of hypermedia.

urzds 2017-04-04T19:23:37.502823Z

The wikipedia definition of hypermedia, e.g., was rather confusing in this context: https://en.wikipedia.org/wiki/Hypermedia

ordnungswidrig 2017-04-04T19:23:59.511272Z

yes, it’s data pointing to other data 🙂

ordnungswidrig 2017-04-04T19:24:31.524322Z

Important is that if you have a, say a resource of type “order” that links to a resource “xyz” and the link is qualified as the relation “payment” that you have documented what this relation means for a resource of type “order”.

urzds 2017-04-04T19:24:41.527969Z

Thanks for the link.

ordnungswidrig 2017-04-04T19:25:05.537092Z

And what is the expected semantics when you POST or DELETE to that link. (e.g. “initiate paymen” and “cancel payment” or “refund payment”)

ordnungswidrig 2017-04-04T19:25:34.548593Z

That’s only documented for the resource types, not for a particular URI. This is a main difference to the RPC based API descriptors like swagger.

urzds 2017-04-04T19:30:47.674085Z

Thanks a lot for all that input. I'll read and then chart a new course taking into account all that new data 🙂

ordnungswidrig 2017-04-04T19:31:00.679602Z

One step after the other 🙂

urzds 2017-04-04T19:57:15.306606Z

omg, clojure is soooo awesome:

clj
(defn error-namespace? [s]
  (= (namespace s) "error"))
...
(s/constrained s/Keyword error-namespace?)
This is actually enough to check my error codes... Incredible...

urzds 2017-04-04T20:00:05.377506Z

I start with an extremely elaborate and thought through way of managing error codes, that only involves a registry and some macros and namespaces and ... And I end up with (basically) a one-liner.