Web Service DSL
WSDSL is a simple DSL allowing developers to simply describe and document their web APIS. For instance:
describe_service "hello_world" do |service|
service.formats :xml
service.http_verb :get
service.disable_auth # on by default
service.param.string :name, :default => 'World'
service.response do |response|
response.element(:name => "greeting") do |e|
e.attribute "message" => :string, :doc => "The greeting message sent back."
end
end
service.documentation do |doc|
doc.overall "This service provides a simple hello world implementation example."
doc.params :name, "The name of the person to greet."
doc.example "<code>http://example.com/hello_world.xml?name=Matt</code>"
end
end
Or a more complex example:
SpecOptions = ['RSpec', 'Bacon'] # usually pulled from a model
describe_service "wsdsl/test.xml" do |service|
service.formats :xml, :json
service.http_verb :get
service.params do |p|
p.string :framework, :in => SpecOptions, :null => false, :required => true
p.datetime :timestamp, :default => Time.now
p.string :alpha, :in => ['a', 'b', 'c']
p.string :version, :null => false
p.integer :num, :minvalue => 42
end
# service.param :delta, :optional => true, :type => 'float'
# All params are optional by default.
# service.param :epsilon, :type => 'string'
service.params.namespace :user do |user|
user.integer :id, :required => :true
end
# the response contains a list of player creation ratings each object in the list
service.response do |response|
response.element(:name => "player_creation_ratings") do |e|
e.attribute :id => :integer, :doc => "id doc"
e.attribute :is_accepted => :boolean, :doc => "is accepted doc"
e.attribute :name => :string, :doc => "name doc"
e.array :name => 'player_creation_rating', :type => 'PlayerCreationRating' do |a|
a.attribute :comments => :string, :doc => "comments doc"
a.attribute :player_id => :integer, :doc => "player_id doc"
a.attribute :rating => :integer, :doc => "rating doc"
a.attribute :username => :string, :doc => "username doc"
end
end
end
service.documentation do |doc|
# doc.overall <markdown description text>
doc.overall <<-DOC
This is a test service used to test the framework.
DOC
# doc.params <name>, <definition>
doc.params :framework, "The test framework used, could be one of the two following: #{SpecOptions.join(", ")}."
doc.params :version, "The version of the framework to use."
# doc.example <markdown text>
doc.example <<-DOC
The most common way to use this service looks like that:
http://example.com/wsdsl/test.xml?framework=rspec&version=2.0.0
DOC
end
end
JSON APIs
This library was designed with XML responses in mind and JSON support was added later on which explains why some response methods are aliases. Consider the following JSON response:
{ people: [
{
id : 1,
online : false,
created_at : 123123123123,
team : {
id : 1231,
score : 123.32
}
},
{
id : 2,
online : true,
created_at : 123123123123,
team: {
id : 1233,
score : 1.32
}
},
] }
It would be described as follows:
describe_service "json_list" do |service|
service.formats :json
service.response do |response|
response.array :people do |node|
node.integer :id
node.boolean :online
node.datetime :created_at
node.object :team do |team|
team.integer :id
team.float :score, :null => true
end
end
end
end
Nodes/elements can also use some meta attributes. Currently the following meta attributes are available:
- key (refers to an attribute name that is key to this object)
- type (refers to the type of object described, valuable when using JSON cross OO based apps.
JSON response validation can be done using an optional module. Look at the spec/json_response_verification_spec.rb file for a complete example. The goal of this module is to help automate API testing by validating the data structure of the returned object.
Test suite
This library comes with a test suite requiring Ruby 1.9.2 The following gems need to be available: Rspec, Rack, Sinatra
RUBY 1.8 warning
This library was written for Ruby 1.9 and 1.8 support was added later on via the backports libary and some tweaks. However, because unlike in ruby 1.9, the hash insert order isn't kept in 1.8 the following syntax isn't supported and the alternative version needs to be used:
service.response do |response|
response.element(:name => "player_creation_ratings") do |e|
e.attribute :id => :integer, :doc => "id doc"
e.attribute :is_accepted => :boolean, :doc => "is accepted doc"
e.attribute :name => :string, :doc => "name doc"
end
end
Instead the following version should be used:
service.response do |response|
response.element(:name => "player_creation_ratings") do |e|
e.integer :id, :doc => "id doc"
e.boolean :is_accepted, :doc => "is accepted doc"
e.string :name, :doc => "name doc"
end
end
Both code snippets do the exact same thing but the first version is 1.9 only.
Copyright
Copyright (c) 2011 Matt Aimonetti. See LICENSE for further details.