-
Notifications
You must be signed in to change notification settings - Fork 78
Options based approach
#3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
I kept working on this and discussed some things with @paf31. It occurred to me that the current We can't just make I had been thinking that users would be able to specify their own I also had some thought about doing away with I can't believe how tricky this pretty simple library is proving to be to get right! |
|
What about a scrap-your-typeclasses approach to |
|
Yes! That would work a lot better, we wouldn't get the missing instance error that way too. |
|
@garyb Do you want a review now or wait till you've done the last few things? |
|
I'll push another update to at least address the |
|
Ok, this is ready for review now. Unfortunately I ran into a problem with orphan instances for the various requestable types too, as they'd need Perhaps the free monad layer on top is even more appealing now, as it would allow us to use a The only outstanding issue I can think of is I need to figure out if there is a way to make the ArrayBuffer responses safe. Or safer at least. The |
README.md
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In all these methods, I'd put the URL first, because you are likely to make many requests to the same URL, whereas each request is likely to have different content. Also I'd use a type URL = String just for doc purposes.
src/Network/HTTP/Affjax.purs
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having to pass in Responsable a is unfortunate. What again was wrong with a type class based approach, e.g.:
class Responsable a where
mimeType :: MimeType
fromForeign :: Foreign -> F a
class Requestable a where
mimeType :: MimeType
toForeign :: a -> ForeignThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The advantage of something like this is that it cleans up the APIs, and you can request / respond any suitable type directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue I had is it would give us orphan instances for Blob, FormData, Document and all the ArrayView types - they need IsOption instances. It also seems like Responsable should be IsForeign a <= Responsable a, as fromForeign is just read from IsForeign, but then we have another orhpan instance situation...
I might revisit the free monad version yet again, maybe there is a way this can be made to work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue I had is it would give us orphan instances for Blob, FormData, Document and all the ArrayView types - they need IsOption instances.
This seems like a limitation of the options library (or our use of the library). Also I'd note the only value this library is providing us with is a monoidal syntax for combining optional options. Which is of questionable benefit given all the FFI magic going on. I'd almost prefer the "base" version just use a record with Maybes for everything, that way you could provide a default with Nothing for everything and users could use update syntax to make changes they want. Then other modules could build on that simple dumb version and do things like free monad DSL, options-style monoidal syntax sugar, etc.
I'd just really like the signature to be something like:
affjax :: forall e a b. (Requestable a, Respondable b) => AjaxRequest a -> Aff (ajax :: AJAX | e) (AjaxResponse b)with affjax function handling setting Content-Type and Accept headers based on the given requestable / respondable (of course, these could be overridden by the user if necessary).
By the way, to some extent I recognize this as bikeshedding, so happy to merge if you like the API as it is. 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that was basically the approach I took in the other branch but then abandoned after having problems with the DSL. I'll take another look at it and see if I can make the core part work as I agree that the class approach is far more attractive.
|
Ok, how's this? The classes are back, the options are just a normal record. I haven't added the content type stuff to
|
|
My only comment on mime types is that mime types are much more specific than the 5 types (Document ,XML, JSON, String, etc.) supported directly by XMLHttpRequest. In general, a client should always specify an I'm going to merge this in now, let's do separate PRs for followup work. |
|
Btw, can you add travis in here so we can get a CI build going? |
|
Great, sorry it took so long to get here! Travis is in another PR, I'll open some issues for the other bits. |
Resolves #1 (maybe!)
options.RequestableandResponsableclasses to deal with conversions of values.contentTypeproperty is set based on the expectedResponsablevalue.ArrayBuffersbeing sent across not coming through with the right length.No instance for Responsable uXXXXerror.get,post, etc. combinators.optionsversion the headers have to be all set together.mandragora-bucketand integrate the tests into the gulp build.unsafeAjax's callback should actually beAffjaxResponse Foreign -> Eff (ajax :: Ajax | e) Unitand thenaffjax'shouldread/fromContentthe value to actually make it into aResponsable b, handling errors somehow.