-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Proposal: Implementable Documentation #620
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
We are currently using the grape/swagger combination with a bunch of clients - about a dozen projects - and I would welcome these changes. Right now the documentation kinda obfuscates the code when it is present inline. And I've had to make customizations to swagger to make it aware of custom HTTP headers that we us for authentication instead of the basic or token auth they support. A fresh start like this would help us clean up a lot of code. |
I wanted to add a +1 to this. |
Hopefully it will be completed and merged. |
Awesome proposal @mbleigh ! 👍 |
Hey, this idea is great. This will allow us to keep extensions like grape-swagger less hacky. 👍 |
Awesome proposal @mbleigh ! 👍 |
👍 Great proposal! |
The code in this PR is definitely nowhere near the detailed description here. So no plans on merging this "as is". |
Yeah, this is something I just haven't had any time to work on to my continued frustration. If someone else is really interested in implementing, I would be super-excited! Otherwise, I'll try to find time somehow, someday. |
@dblock ok! Perhaps it would be more practical for the entity class to respond to a |
What should we do about this PR? Bump @mbleigh. |
I am going to close this. This can definitely be implemented today as a Grape extension if someone wants to take it further into a gem. |
I've been pondering on this one for a while, so I'm just going to lay out some of the fundamentals I've been thinking about and go from there. Currently we have
desc
andparams
and some arbitrary conventions that help feedgrape-swagger
. I think we can do better. This proposal is somewhat based on some hacks we've done at Divshot and partially based on what I think makes sense.The heart of this proposal is making
desc
a block-accepting method that yields a documentation DSL. With this DSL,params
may be (optionally) nested inside thedesc
block or provided separately.Standardized Error Format
It is useful to have both human and machine readable error conditions for APIs. Currently Grape has a simple
{"error":"<message>"}
format but this is often not enough information by itself. I propose the following format:This format is compatible with the OAuth 2.0 error response formats (which is why I named things as I did) with the addition of
context
, which might provide (for example) which parameters were invalid.This format would replace the current default error formatter and in an endpoint would look something like:
I'm moving the
status
to the front of the queue here both because it allows us to potentially implement in a backwards-compatible way and because the HTTP Status is one of the most important pieces of info that can be communicated and I now think it was a mistake to make it an optional parameter. You should always think about and provide a sane HTTP status on error.Declarative Response Modes
For the purposes of documentation, automated tooling, etc. it is very useful to know what the characteristics of all possible responses to an endpoint are. I propose that the
desc
DSL includesuccess
andfailure
methods that work like so:I believe that a DSL like this will create great at-a-glance documentation in the code itself while also providing all the metadata needed to generate documentation. Unlike the existing "do whatever you want in the desc hash" setup, the failure modes and success modes can actually affect endpoint behavior.
The
fail!
method works much likeerror!
except it only allows failure modes that have already been defined indesc
blocks.Reusing Failure Modes
It will often be convenient to reuse a failure mode. This will be done the same way that it is today with
params
:Of course you can do this on
scope
as well to avoid creating a new namespace:Entity Definition
The second argument of the
success
call above is an entity class. The only thing required of an entity class is that it respond toentity_schema
and return a hash that looks something like this:This would be built in to
Grape::Entity
obviously, but could be easily implemented in other representation systems as well.Markdown and More
The DSL above provides great facilities for terse description of API endpoints. However, for more in-depth content putting that in the
.rb
files doesn't really make sense. This is less thought through, but here's one option:desc
DSL, also accept a symbol.This should basically work by loading a big hash, as you'd expect.
What I think I would want to do, personally, is build a system based on Markdown that would parse out H1s to get key names. I was going to go into detail but I think that actually makes more sense as a separate library.
Expanding Documentation Output
With a more robust documentation system built into Grape, it would be easy to support all of the various API description libraries (we have Swagger now, but could then support Blueprint and others without much trouble).
OK, that's the longest issue description I've ever written. Thoughts? I want some feedback before I'd start diving into implementation.