This gem provides helpers to annotate Sinatra routes and automatically generate HTML API documentation.
Routes can be annotated with information such as:
- summary (short description)
- notes (extended description)
- content type produced
- returning status codes
In addition, examples can be linked to routes and automatically associated. See the section "Associating examples" for more information.
DocMyRoutes can be installed via Rubygems or compiling and installing it yourself as:
$ gem build doc_my_routes.gemspec
$ gem install doc_my_routes-VERSION.gem
Using DocMyRoutes is quite straight-forward and it basically requires two steps:
- configure DocMyRoutes and annotate your application
- triggering the generation of the documentation
First of all, DocMyRoutes needs to be configured with your project title and description (see the Customisation section for other options).
Simply require 'doc_my_routes'
and set the two options:
DocMyRoutes.configure do |config|
config.title = "My Application"
config.description = "My Application description"
end
then extend DocMyRoutes::Annotatable
in your Sinatra application and start annotating your routes.
Example:
require 'sinatra/base'
require 'doc_my_routes'
DocMyRoutes.configure do |config|
config.title = "My Application"
config.description = "My Application description"
end
class MyApp < Sinatra::Base
# Add support for documenting routes
extend DocMyRoutes::Annotatable
summary 'Example route'
notes 'Simple route that gets an ID and returns a string'
produces 'text/plain'
status_codes [200]
parameter :id, description: 'some ID'
get '/:id' do |id|
"Received #{id}"
end
end
Note that configuring format = :partial_html
generates an HTML snippet
that can be easily embedded, instead of a complete HTML page.
### Generating documentation
In your config.ru (or in your main .rb file) you can trigger the generation
of the documentation invoking DocMyRoutes::Documentation.generate
.
Example:
require_relative 'my_app'
# Configure your app here...
...
# If documentation requested (e.g., using an input flag)
DocMyRoutes::Documentation.generate
...
This will generate HTML API documentation to the configured destination_dir
. By default the destination directory is doc/api
.
### Associating examples
In addition to the helpers described above, DocMyRoutes provides a
examples_regex
helper that will automatically link call examples to the
documentation of that route.
An example represents a request/response interaction related to that route and it's application specific. DocMyRoutes provides a structure to automatically link them to a given route.
Examples must follow a specific format, in order to be correctly used.
- Must be in YAML format
- Must have a name key associated, used to filter examples
- Must have an action key, that defines the action of that route (i.e., GET /myroute)
- Must have a request section, that might contain the following optional fields:
- params: string defining an example query
- headers: key-values of the headers sent
- body: the body of the request
- Must have a response section, that might contain the following optional fields:
- status: status of the response
- headers: key-values of the headers received
- body: the body of the response
The field name is used to defined, based on the value of the helper
examples_regex
, if that example should be associated to that route.
The body can be free format.
A valid example and its association to a route are shown below.
Route annotation:
examples_regex 'myapp_get_*'
get '/myapp' do
'Hello'
end
Example:
---
action: GET /myapp
request:
headers:
MY-APP-ID: example-id
response:
headers:
content-type: text/plain;charset=utf-8
status: 200
body: 'Hello'
name: my_app_get_hello_example
description: Simple example of a GET that returns Hello
Once the examples are available and the routes are annotated accordingly, DocMyRoutes can be configured to load and parse all the files that match a given regexp.
DocMyRoutes.configure do |config|
config.examples_path_regexp = 'myapp/examples/*.yml'
end
DocMyRoutes can generate documentation for most Sinatra applications and it also automatically detects when an application is mounted on a different path.
The following two examples both would work.
Using map:
require_relative 'my_app'
app = Rack::Builder.app do
map '/myapp' do
run MyApp.new
end
end
...
# If documentation requested (e.g., using an input flag)
DocMyRoutes::Documentation.generate
...
Or using URLMap:
require_relative 'my_app'
app = Rack::Builder.app do
run Rack::URLMap.new('/myapp' => MyApp.new)
end
...
# If documentation requested (e.g., using an input flag)
DocMyRoutes::Documentation.generate
...
Note: there are occasions where an application may be mounted using url map and be composed of other apps by making use of the 'use' directive in rack. In this case, you need to tell DocMyRoutes to link the two together. By doing this, DocMyRoutes will automatically provide documentation for the child apps mounted wherever the composed app ends up being mounted.
e.g.
class MyChildApp; end
class MyOtherChildApp; end
class MyComposedApp
DocMyRoutes::Mapping.inherit_mapping(MyChildApp, self)
DocMyRoutes::Mapping.inherit_mapping(MyOtherChildApp, self)
use MyChildApp
use MyOtherChildApp
end
app = Rack::Builder.app do
run Rack::URLMap.new('/myapp' => MyComposedApp.new)
end
Some aspects of DocMyRoutes can be customised to provide a different user experience.
The next few sections describe the available settings; simply have code like the following snippet to change those settings.
require 'doc_my_routes'
DocMyRoutes.configure do |config|
config.SETTING = MY_VALUE
end
The settings title
and description
control the
first section of the documentation and should always be configured.
The setting destination_dir
defines where to store the generated
documentation.
The output format may be customised by setting the format
setting. At present :html
and :partial_html
are supported (default :html
). :html
produces a full html page with a head and body section. :partial_html
produces the documentation that maybe embedded in another webpage.
A custom CSS file can be provided to change the look and feel of the documentation.
The setting css_file_path
controls which file is going to be loaded and
used.
The simplified structure with custom classes of the current template is shown in the following snippet and can be used a guideline of what can be easily customised.
section.documentation
header
info.title
info.description
section.resources
article.resource (repeated for every resource)
summary.resource
article.operation {.get, .put, .post, .delete} (for every operation)
summary.operation
div.content {.get, .put, .post, .delete}
... actual content ...
article.example {.get, .put, .post, .delete}
summary.example {.get, .put, .post, .delete}
div.example_content {.get, .put, .post, .delete}
div.request
div.code {.get, .put, .post, .delete}
pre.request-code.query
pre.request-code.headers
pre.request-code.body
div.response
div.code {.get, .put, .post, .delete}
pre.request-code.headers
pre.request-code.body
A custom logger can be provided using:
require 'doc_my_routes'
DocMyRoutes.logger = MY_CUSTOM_LOGGER
class MyApp < Sinatra::Base
extend DocMyRoutes::Annotatable
...
If a custom logger is not configured, a standard one that writes to STDOUT is provided by default.
- Multiple Rack applications inheriting from the same parent application are not supported at the moment. (see spec/system/childapps_spec.rb for an example)
- Firefox and IE do not support the HTML5 details tag and hence the route section are not collapsible
Please refer to CONTRIBUTING and LICENSE for more information.