sinatra-doc 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/README.md +41 -0
- data/VERSION +1 -0
- data/app.rb +70 -0
- data/config.ru +2 -0
- data/lib/doc.rb +83 -0
- data/test/doc_test.rb +82 -0
- data/test/test_helper.rb +3 -0
- metadata +63 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
.DS_Store
|
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# sinatra-doc
|
2
|
+
|
3
|
+
self documentaion for your [sinatra]("http://sinatrarb.com") app's routes
|
4
|
+
|
5
|
+
# usage
|
6
|
+
|
7
|
+
see the reference implementation [app.rb](http://github.com/softprops/sinatra-doc/blob/master/app.rb)
|
8
|
+
|
9
|
+
> your app.rb
|
10
|
+
|
11
|
+
class App < Sinatra::Base
|
12
|
+
register Sinatra::Doc
|
13
|
+
|
14
|
+
doc "gets a list of foos"
|
15
|
+
get "foos" { ... }
|
16
|
+
|
17
|
+
doc "gets a specific foo", {
|
18
|
+
:id => "identifier for a given foo"
|
19
|
+
}
|
20
|
+
get "foos/:id" { ... }
|
21
|
+
end
|
22
|
+
|
23
|
+
> GET /doc
|
24
|
+
|
25
|
+
sinatra doc
|
26
|
+
|
27
|
+
GET foos gets a list of foos
|
28
|
+
|
29
|
+
GET foos/:id gets a specific foo
|
30
|
+
:id identifier for a given foo
|
31
|
+
|
32
|
+
# Props
|
33
|
+
|
34
|
+
based on an idea [@bmizerany]("http://twitter.com/bmizerany") proposed in a [heroku]("http://heroku.com/") talk in nyc
|
35
|
+
|
36
|
+
# TODO
|
37
|
+
|
38
|
+
* rake sinatra::doc #=> à la rails rake:routes
|
39
|
+
* clean up rendering of docs
|
40
|
+
|
41
|
+
2009 softprops (doug tangren)
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/app.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require File.join(File.dirname(__FILE__), *%w(lib doc))
|
3
|
+
|
4
|
+
# a reference usage of Sinatra::Doc
|
5
|
+
module Kittens
|
6
|
+
class App < Sinatra::Base
|
7
|
+
register Sinatra::Doc do
|
8
|
+
def title
|
9
|
+
"kittenz api"
|
10
|
+
end
|
11
|
+
|
12
|
+
def header
|
13
|
+
(<<-HEADER)
|
14
|
+
<h1>
|
15
|
+
<pre>
|
16
|
+
kittenz
|
17
|
+
_
|
18
|
+
\`*-.
|
19
|
+
) _`-.
|
20
|
+
. : `. .
|
21
|
+
: _ ' \
|
22
|
+
; *` _. `*-._
|
23
|
+
`-.-' `-.
|
24
|
+
; ` `.
|
25
|
+
:. . \
|
26
|
+
. \ . : .-' .
|
27
|
+
' `+.; ; ' :
|
28
|
+
: ' | ; ;-.
|
29
|
+
; ' : :`-: _.`* ;
|
30
|
+
.*' / .*' ; .*`- +' `*'
|
31
|
+
`*-* `*-* `*-*'
|
32
|
+
</pre>
|
33
|
+
</h1>
|
34
|
+
HEADER
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
doc 'lists all kittens'
|
39
|
+
get '/kittens' do
|
40
|
+
'...'
|
41
|
+
end
|
42
|
+
|
43
|
+
doc 'gets a kitten by name', {
|
44
|
+
:name => "name of kitten"
|
45
|
+
}
|
46
|
+
get '/kittens/:name' do |name|
|
47
|
+
"..."
|
48
|
+
end
|
49
|
+
|
50
|
+
doc 'creates a new kitten'
|
51
|
+
post '/kittens' do
|
52
|
+
'...'
|
53
|
+
end
|
54
|
+
|
55
|
+
doc 'updates a kitten', {
|
56
|
+
:name => 'name of kitten'
|
57
|
+
}
|
58
|
+
put "/kittens/:id" do
|
59
|
+
'...'
|
60
|
+
end
|
61
|
+
|
62
|
+
doc 'deletes a given kitten', {
|
63
|
+
:name => 'name of kitten'
|
64
|
+
}
|
65
|
+
delete '/kittens/:name' do |name|
|
66
|
+
'...'
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
data/config.ru
ADDED
data/lib/doc.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
module Sinatra
|
2
|
+
# executable api documentation
|
3
|
+
module Doc
|
4
|
+
class Route
|
5
|
+
attr_accessor :desc, :params, :paths
|
6
|
+
|
7
|
+
def initialize(attrs={})
|
8
|
+
attrs.each_pair { |k,v| send "#{k}=",v if respond_to? "#{k}=" }
|
9
|
+
self.paths = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def <<(path)
|
13
|
+
self.paths << path
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
self.inspect
|
18
|
+
end
|
19
|
+
|
20
|
+
def inspect
|
21
|
+
"#{@paths.join(', ')} # #{@desc}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.registered(app)
|
26
|
+
app.get '/doc' do
|
27
|
+
app.instance_eval { render_docs_page(@docs) }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def doc(desc, params = {})
|
32
|
+
@last_doc = Route.new(:desc => desc, :params => params)
|
33
|
+
(@docs ||= []) << @last_doc
|
34
|
+
end
|
35
|
+
|
36
|
+
def title
|
37
|
+
"sinatra doc"
|
38
|
+
end
|
39
|
+
|
40
|
+
def header
|
41
|
+
"<h1>%s</h1>" % title
|
42
|
+
end
|
43
|
+
|
44
|
+
def method_added(method)
|
45
|
+
return if method.to_s =~ /(^(GET|HEAD) \/doc\z)/
|
46
|
+
if method.to_s =~ /(GET|POST|PUT|DELETE|UPDATE|HEAD)/ && @last_doc
|
47
|
+
@last_doc << method
|
48
|
+
@last_doc = nil
|
49
|
+
end
|
50
|
+
super
|
51
|
+
end
|
52
|
+
|
53
|
+
def render_docs_list(routes)
|
54
|
+
routes.inject('<dl>') { |markup, route|
|
55
|
+
path = route.paths.join(', ')
|
56
|
+
desc = route.desc
|
57
|
+
params = route.params.inject('') { |li,(k,v)|
|
58
|
+
li << "<dt>:%s</dt><dd>%s</dd>" % [k,v]
|
59
|
+
}
|
60
|
+
markup << "<dt>%s</dt><dd>%s<dl>%s</dl></dd>" % [path, desc, params]
|
61
|
+
} << "</dl>"
|
62
|
+
end
|
63
|
+
|
64
|
+
def render_docs_page(routes)
|
65
|
+
(<<-HTML)
|
66
|
+
<html>
|
67
|
+
<head><title>#{title}</title></head>
|
68
|
+
<style type="text/css">
|
69
|
+
#container{width:960px; margin:1em auto; font-family:monaco, monospace;}
|
70
|
+
dt{ background:#f5f5f5; font-weight:bold; float:left; margin-right:1em; }
|
71
|
+
dd{ margin-left:1em; }
|
72
|
+
</style>
|
73
|
+
<body>
|
74
|
+
<div id="container">
|
75
|
+
#{header}
|
76
|
+
#{render_docs_list(routes)}
|
77
|
+
</div>
|
78
|
+
</body>
|
79
|
+
</html>
|
80
|
+
HTML
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/test/doc_test.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w(test_helper))
|
2
|
+
|
3
|
+
class DocTest < Test::Unit::TestCase
|
4
|
+
class A < Sinatra::Base
|
5
|
+
register Sinatra::Doc
|
6
|
+
|
7
|
+
doc "gets a list of materia"
|
8
|
+
get "/materia" do
|
9
|
+
"..."
|
10
|
+
end
|
11
|
+
|
12
|
+
get "/undocumented" do
|
13
|
+
"..."
|
14
|
+
end
|
15
|
+
|
16
|
+
doc "gets a specific materia", {
|
17
|
+
:kind => "color of the materia [red,green,blue,yellow,purple]"
|
18
|
+
}
|
19
|
+
get "/materia/:kind" do
|
20
|
+
"..."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class B < Sinatra::Base
|
25
|
+
register Sinatra::Doc do
|
26
|
+
def title
|
27
|
+
"Beez Kneez"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
doc "get a list of bees"
|
32
|
+
get "/bees" do
|
33
|
+
"..."
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def documented_app
|
38
|
+
A
|
39
|
+
end
|
40
|
+
|
41
|
+
def documented_app_with_overrides
|
42
|
+
B
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'a documented sinatra app' do
|
46
|
+
should 'have a documented api' do
|
47
|
+
browser = Rack::Test::Session.new(
|
48
|
+
Rack::MockSession.new(documented_app)
|
49
|
+
)
|
50
|
+
browser.get '/doc'
|
51
|
+
assert browser.last_response.ok?
|
52
|
+
[
|
53
|
+
"GET /materia",
|
54
|
+
"gets a list of materia",
|
55
|
+
"/materia/:kind",
|
56
|
+
"gets a specific materia",
|
57
|
+
"color of the materia [red,green,blue,yellow,purple]"
|
58
|
+
].each { |phrase|
|
59
|
+
assert browser.last_response.body.include?(phrase)
|
60
|
+
}
|
61
|
+
|
62
|
+
assert !browser.last_response.body.include?("/undocumented")
|
63
|
+
end
|
64
|
+
|
65
|
+
context "with doc overrides" do
|
66
|
+
should "render with overrides" do
|
67
|
+
browser = Rack::Test::Session.new(
|
68
|
+
Rack::MockSession.new(documented_app_with_overrides)
|
69
|
+
)
|
70
|
+
browser.get '/doc'
|
71
|
+
assert browser.last_response.ok?
|
72
|
+
[
|
73
|
+
"Beez Kneez",
|
74
|
+
"GET /bees",
|
75
|
+
"get a list of bees"
|
76
|
+
].each { |phrase|
|
77
|
+
assert browser.last_response.body.include?(phrase)
|
78
|
+
}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sinatra-doc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Doug Tangren
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-04 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: self documentaion for your sinatra app's routes
|
17
|
+
email: d.tangren@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.md
|
24
|
+
files:
|
25
|
+
- .gitignore
|
26
|
+
- README.md
|
27
|
+
- VERSION
|
28
|
+
- app.rb
|
29
|
+
- config.ru
|
30
|
+
- lib/doc.rb
|
31
|
+
- test/doc_test.rb
|
32
|
+
- test/test_helper.rb
|
33
|
+
has_rdoc: true
|
34
|
+
homepage: http://github.com/softprops/sinatra-doc
|
35
|
+
licenses: []
|
36
|
+
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options:
|
39
|
+
- --charset=UTF-8
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
version:
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
version:
|
54
|
+
requirements: []
|
55
|
+
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 1.3.5
|
58
|
+
signing_key:
|
59
|
+
specification_version: 3
|
60
|
+
summary: self documentaion for your sinatra app's routes
|
61
|
+
test_files:
|
62
|
+
- test/doc_test.rb
|
63
|
+
- test/test_helper.rb
|