Generate pretty API docs for your Rails APIs.
Check out a sample.
Please see the wiki for latest changes.
Add rspec_api_documentation to your Gemfile
gem 'rspec_api_documentation'
Bundle it!
$ bundle install
Set up specs.
$ mkdir spec/acceptance
$ vim spec/acceptance/orders_spec.rb
require 'spec_helper'
require 'rspec_api_documentation/dsl'
resource "Orders" do
get "/orders" do
example "Listing orders" do
do_request
status.should == 200
end
end
end
Generate the docs!
$ rake docs:generate
$ open doc/api/index.html
Also consider adding Raddocs as a viewer. It has much better HTML output than rspec_api_documentation.
gem 'raddocs'
RspecApiDocumentation.configure do |config|
config.format = :json
end
See the example
folder for a sample Rails app that has been documented.
# Values listed are the default values
RspecApiDocumentation.configure do |config|
# Set the application that Rack::Test uses
config.app = Rails.application
# Output folder
config.docs_dir = Rails.root.join("doc", "api")
# An array of output format(s). Possible values are :json, :html
config.format = [:html]
# Location of templates
config.template_path = "inside of the gem"
# Filter by example document type
config.filter = :all
# Filter by example document type
config.exclusion_filter = nil
# Used when adding a cURL output to the docs
config.curl_host = nil
# By default examples and resources are ordered by description. Set to true keep
# the source order.
config.keep_source_order = false
# Change the name of the API on index pages
config.api_name = "API Documentation"
# Redefine what method the DSL thinks is the client
# This is useful if you need to `let` your own client, most likely a model.
config.client_method = :client
# You can define documentation groups as well. A group allows you generate multiple
# sets of documentation.
config.define_group :public do |config|
# By default the group's doc_dir is a subfolder under the parent group, based
# on the group's name.
config.docs_dir = Rails.root.join("doc", "api", "public")
# Change the filter to only include :public examples
config.filter = :public
end
end
rspec_api_documentation lets you determine which examples get outputted into the final documentation.
All filtering is done via the :document
metadata key.
You tag examples with either a single symbol or an array of symbols.
:document
can also be false, which will make sure it does not get outputted.
resource "Account" do
get "/accounts" do
parameter :page, "Page to view"
# default :document is :all
example "Get a list of all accounts" do
do_request
status.should == 200
end
# Don't actually document this example, purely for testing purposes
example "Get a list on page 2", :document => false do
do_request(:page => 2)
status.should == 404
end
# With example_request, you can't change the :document
example_request "Get a list on page 3", :page => 3 do
status.should == 404
end
end
post "/accounts" do
parameter :email, "User email"
example "Creating an account", :document => :private do
do_request(:email => "[email protected]")
status.should == 201
end
example "Creating an account - errors", :document => [:private, :developers] do
do_request
status.should == 422
end
end
end
# All documents will be generated into the top folder, :document => false
# examples will never be generated.
RspecApiDocumentation.configure do |config|
# Exclude only document examples marked as 'private'
config.define_group :non_private do |config|
config.exclusion_filter = :private
end
# Only document examples marked as 'public'
config.define_group :public do |config|
config.filter = :public
end
# Only document examples marked as 'developer'
config.define_group :developers do |config|
config.filter = :developers
end
end
At the beginning of each acceptance/*_spec.rb file, make sure to require the following to pull in the DSL definitions:
require 'rspec_api_documentation/dsl'
Create a set of documentation examples that go together. Acts as a describe block.
resource "Orders" do
end
The method that will be sent along with the url.
resource "Orders" do
post "/orders" do
end
get "/orders" do
end
head "/orders" do
end
put "/orders/:id" do
let(:id) { order.id }
example "Get an order" do
path.should == "/orders/1" # `:id` is replaced with the value of `id`
end
end
delete "/orders/:id" do
end
patch "/orders/:id" do
end
end
This is just RSpec's built in example method, we hook into the metadata surrounding it. it
could also be used.
resource "Orders" do
post "/orders" do
example "Creating an order" do
do_request
# make assertions
end
end
end
The same as example, except it calls do_request
as the first step. Only assertions are required in the block.
Similar to do_request
you can pass in a hash as the last parameter that will be passed along to do_request
as extra parameters. These will not become metadata like with example
.
resource "Orders" do
parameter :name, "Order name"
post "/orders" do
example_request "Creating an order", :name => "Other name" do
# make assertions
end
end
end
This method takes the parameter name, a description, and an optional hash of extra metadata that can be displayed in Raddocs as extra columns. If a method with the parameter name exists, e.g. a let
, it will send the returned value up to the server as URL encoded data.
Special values:
:required => true
Will display a red '*' to show it's required:scope => :the_scope
Will scope parameters in the hash. See example
resource "Orders" do
parameter :auth_token, "Authentication Token"
let(:auth_token) { user.authentication_token }
post "/orders" do
parameter :name, "Order Name", :required => true, :scope => :order
let(:name) { "My Order" }
example "Creating an order" do
params.should == { :order => { :name => "My Order" }, :auth_token => auth_token }
end
end
end
This is complicated, see relish docs.
Pass this method a block which, when evaluated, will cause the application to make a request to callback_url
.
Defines the destination of the callback.
For an example, see relish docs.
Returns the test client which makes requests and documents the responses.
resource "Order" do
get "/orders" do
example "Listing orders" do
# Create an order via the API instead of via factories
client.post "/orders", order_hash
do_request
status.should == 200
end
end
end
This will evaluate the block passed to trigger_callback
, which should cause the application under test to make a callback request. See relish docs.
Sends the request to the app with any parameters and headers defined.
resource "Order" do
get "/orders" do
example "Listing orders" do
do_request
status.should == 200
end
end
end
If you wish to make a request via the client that should not be included in your documentation, do it inside of a no_doc block.
resource "Order" do
get "/orders" do
example "Listing orders" do
no_doc do
# Create an order via the API instead of via factories, don't document it
client.post "/orders", order_hash
end
do_request
status.should == 200
end
end
end
Get a hash of parameters that will be sent. See parameter
documentation for an example.
Returns a string containing the response body from the previous request.
resource "Order" do
get "/orders" do
example "Listing orders" do
do_request
response_body.should == [{ :name => "Order 1" }].to_json
end
end
end
Returns a hash of the response headers from the previous request.
resource "Order" do
get "/orders" do
example "Listing orders" do
do_request
response_headers["Content-Type"].should == "application/json"
end
end
end
Returns the numeric status code from the response, eg. 200. response_status
is an alias to status because status is commonly a parameter.
resource "Order" do
get "/orders" do
example "Listing orders" do
do_request
status.should == 200
response_status.should == 200
end
end
end
Data that will be sent as a query string instead of post data. Used in GET requests.
resource "Orders" do
parameter :name
let(:name) { "My Order" }
get "/orders" do
example "List orders" do
query_string.should == "name=My+Orders"
end
end
end
The gem contains a Railtie that defines a rake task for generating docs easily with Rails.
It loads all files in spec/acceptance/**/*_spec.rb
.
$ rake docs:generate
If you are not using Rails, you can use Rake with the following Task:
require 'rspec/core/rake_task'
desc 'Generate API request documentation from API specs'
RSpec::Core::RakeTask.new('docs:generate') do |t|
t.pattern = 'spec/acceptance/**/*_spec.rb'
t.rspec_opts = ["--format RspecApiDocumentation::ApiFormatter"]
end
or
require 'rspec_api_documentation'
load 'tasks/docs.rake'
If you are not using Rake:
$ rspec spec/acceptance --format RspecApiDocumentation::ApiFormatter
- rspec_api_documentation relies on a variable
client
to be the test client. If you define your ownclient
please configure rspec_api_documentation to use another one, see Configuration above. - We make heavy use of RSpec metadata, you can actually use the entire gem without the DSL if you hand write the metadata.