Automate your documentation writing proces! Dox generates API documentation from Rspec controller/request specs in a Rails application. It formats the tests output in the API Blueprint format. Choose one of the renderes to convert it to HTML or host it on Apiary.io
Here's a demo app and here are some examples:
Add this line to your application's Gemfile:
group :test do
gem 'dox', require: false
end
And then execute:
$ bundle
Or install it yourself as:
$ gem install dox
Require Dox in the rails_helper:
require 'dox'
and configure rspec with this:
RSpec.configure do |config|
config.after(:each, :dox) do |example|
example.metadata[:request] = request
example.metadata[:response] = response
end
end
Set these mandatory options in the rails_helper:
Option | Value | Description |
---|---|---|
header_file_path | Pathname instance or fullpath string | Markdown file that will be included at the top of the documentation. It should contain title and some basic info about the api. |
desc_folder_path | Pathname instance or fullpath string | Folder with markdown descriptions. |
Optional settings:
Option | Value | Description |
---|---|---|
headers_whitelist | Array of headers (strings) | Requests and responses will by default list only Content-Type header. To list other http headers, you must whitelist them. |
Example:
Dox.configure do |config|
config.header_file_path = Rails.root.join('spec/docs/v1/descriptions/header.md')
config.desc_folder_path = Rails.root.join('spec/docs/v1/descriptions')
config.headers_whitelist = ['Accept', 'X-Auth-Token']
end
Define a descriptor module for a resource using Dox DSL:
module Docs
module V1
module Bids
extend Dox::DSL::Syntax
# define common resource data for each action
document :api do
resource 'Bids' do
endpoint '/bids'
group 'Bids'
end
end
# define data for specific action
document :index do
action 'Get bids'
end
end
end
end
You can define the descriptors for example in specs/docs folder, just make sure you load them in the rails_helper.rb:
Dir[Rails.root.join('spec/docs/**/*.rb')].each { |f| require f }
Include the descriptor modules in a controller and tag the specs you want to document with dox:
describe Api::V1::BidsController, type: :controller do
# include resource module
include Docs::V1::Bids::Api
describe 'GET #index' do
# include action module
include Docs::V1::Bids::Index
it 'returns a list of bids', :dox do
get :index
expect(response).to have_http_status(:ok)
end
end
end
And generate the documentation.
Before running into any more details, here's roughly how is the generated API Blueprint document structured:
- header
- resource group
- resource
- action
- example 1
- example 2
- action
- ...
- action
- resource
- action
- ...
- resource
- resource group
- resource
- action
- resource
Header is defined in a markdown file as mentioned before. Examples are concrete test examples (you can have 2 examples for create 1 happy path, 1 fail path). They are completely automatically generated from the request/response objects. And you can customize the following in the descriptors:
- resource group
- resource
- action
Resource group contains related resources and is defined with:
- name (required)
- desc (optional, inline string or relative filepath)
Example:
document :bids_group do
group 'Bids' do
desc 'Here are all bid related resources'
end
end
You can omit defining the resource group, if you don't have any description for it. Related resources will be linked in a group by the group option at the resource definition.
Resource contains actions and is defined with:
- name (required)
- endpoint (required)
- group (required; to associate it with the related group)
- desc (optional; inline string or relative filepath)
Example:
document :bids do
resource 'Bids' do
endpoint '/bids'
group 'Bids'
desc 'bids/bids.md'
end
end
Usually you'll want to define resource and resource group together, so you don't have to include 2 modules with common data per spec file:
document :bids_common do
group 'Bids' do
desc 'Here are all bid related resources'
end
resource 'Bids' do
endpoint '/bids'
group 'Bids'
desc 'bids/bids.md'
end
end
Action is defined with:
- name (required)
- path* (optional)
- verb* (optional)
- params* (optional)
- desc (optional; inline string or relative filepath)
* these optional attributes are guessed (if not defined) from the request object of the test example and you can override them.
Example:
show_params = { id: { type: :number, required: :required, value: 1, description: 'bid id' } }
document :action do
action 'Get bid' do
path '/bids/{id}'
verb 'GET'
params show_params
desc 'Some description for get bid action'
end
end
Documentation is generated in 2 steps:
-
generate API Blueprint markdown:
bundle exec rspec spec/controllers/api/v1 -f Dox::Formatter --order defined --tag dox --out docs.md
-
render HTML with some renderer, for example, with Aglio:
aglio -i docs.md -o docs.html
It's recommendable to write a few rake tasks to make things easier. Here's an example:
namespace :api do
namespace :doc do
desc 'Generate API documentation markdown'
task :md do
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:api_spec) do |t|
t.pattern = 'spec/controllers/api/v1/'
t.rspec_opts = "-f Dox::Formatter --order defined --tag dox --out public/api/docs/v1/apispec.md"
end
Rake::Task['api_spec'].invoke
end
task html: :md do
`aglio -i public/api/docs/v1/apispec.md -o public/api/docs/v1/index.html`
end
task open: :html do
`open public/api/docs/v1/index.html`
end
task publish: :md do
`apiary publish --path=public/api/docs/v1/apispec.md --api-name=doxdemo`
end
end
end
You can render the HTML yourself with one of the renderers:
Both support multiple themes and template customization.
Or you can just take your generated markdown and host your documentation on Apiary.io.
You might experience some strange issues when generating the documentation. Here are a few examples of what we've encountered so far.
Rails wraps JSON parameters on all requests by default, which results with documented requests looking like this:
+ Request get pokemons
{
"pokemon": {}
}
To disable wrapping parameters with a resource name, turn off this feature in config/initializers/wrap_parameters.rb
:
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
ActiveSupport.on_load(:action_controller) do
wrap_parameters format: []
end
You might get the following warnings when rendering HTML with Aglio:
no headers specified (warning code 3)
empty request message-body (warning code 6)
This usually happens on GET requests examples when there are no headers. To solve this issue, add at least one header to the tests' requests, like Accept: application/json
.
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/infinum/dox. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
Dox is maintained and sponsored by Infinum.
The gem is available as open source under the terms of the MIT License.