api_tommy 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.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.rubocop.yml +603 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +70 -0
- data/LICENSE.txt +22 -0
- data/README.md +193 -0
- data/Rakefile +7 -0
- data/api_tommy.gemspec +31 -0
- data/lib/api_tommy.rb +11 -0
- data/lib/api_tommy/error.rb +3 -0
- data/lib/api_tommy/generator.rb +131 -0
- data/lib/api_tommy/github.rb +39 -0
- data/lib/api_tommy/markdown.rb +41 -0
- data/lib/api_tommy/version.rb +3 -0
- data/lib/rdoc/discover.rb +3 -0
- data/lib/rdoc/generator/api_tommy.rb +25 -0
- data/test/fixtures/footer.md +1 -0
- data/test/fixtures/header.md +1 -0
- data/test/fixtures/samples_controller.rb +47 -0
- data/test/lib/api_tommy/github_test.rb +49 -0
- data/test/lib/api_tommy/markdown_test.rb +32 -0
- data/test/lib/rdoc/generator/api_tommy_test.rb +95 -0
- data/test/test_helper.rb +16 -0
- metadata +203 -0
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.2.0
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
api_tommy (0.1.0)
|
5
|
+
activesupport (~> 4.2)
|
6
|
+
grit (~> 2.5)
|
7
|
+
rdoc (~> 4.2)
|
8
|
+
tomparse (~> 0.4)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
activesupport (4.2.0)
|
14
|
+
i18n (~> 0.7)
|
15
|
+
json (~> 1.7, >= 1.7.7)
|
16
|
+
minitest (~> 5.1)
|
17
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
18
|
+
tzinfo (~> 1.1)
|
19
|
+
ansi (1.5.0)
|
20
|
+
builder (3.2.2)
|
21
|
+
coderay (1.1.0)
|
22
|
+
diff-lcs (1.2.5)
|
23
|
+
docile (1.1.5)
|
24
|
+
grit (2.5.0)
|
25
|
+
diff-lcs (~> 1.1)
|
26
|
+
mime-types (~> 1.15)
|
27
|
+
posix-spawn (~> 0.3.6)
|
28
|
+
i18n (0.7.0)
|
29
|
+
json (1.8.2)
|
30
|
+
metaclass (0.0.1)
|
31
|
+
method_source (0.8.2)
|
32
|
+
mime-types (1.25.1)
|
33
|
+
minitest (5.5.0)
|
34
|
+
minitest-reporters (1.0.8)
|
35
|
+
ansi
|
36
|
+
builder
|
37
|
+
minitest (>= 5.0)
|
38
|
+
ruby-progressbar
|
39
|
+
mocha (0.14.0)
|
40
|
+
metaclass (~> 0.0.1)
|
41
|
+
multi_json (1.10.1)
|
42
|
+
posix-spawn (0.3.9)
|
43
|
+
pry (0.10.1)
|
44
|
+
coderay (~> 1.1.0)
|
45
|
+
method_source (~> 0.8.1)
|
46
|
+
slop (~> 3.4)
|
47
|
+
rake (10.4.2)
|
48
|
+
rdoc (4.2.0)
|
49
|
+
ruby-progressbar (1.7.1)
|
50
|
+
simplecov (0.9.1)
|
51
|
+
docile (~> 1.1.0)
|
52
|
+
multi_json (~> 1.0)
|
53
|
+
simplecov-html (~> 0.8.0)
|
54
|
+
simplecov-html (0.8.0)
|
55
|
+
slop (3.6.0)
|
56
|
+
thread_safe (0.3.4)
|
57
|
+
tomparse (0.4.2)
|
58
|
+
tzinfo (1.2.2)
|
59
|
+
thread_safe (~> 0.1)
|
60
|
+
|
61
|
+
PLATFORMS
|
62
|
+
ruby
|
63
|
+
|
64
|
+
DEPENDENCIES
|
65
|
+
api_tommy!
|
66
|
+
minitest-reporters (~> 1.0)
|
67
|
+
mocha (~> 0.14)
|
68
|
+
pry (~> 0.10)
|
69
|
+
rake (~> 10.4)
|
70
|
+
simplecov (~> 0.8)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 David Fernandez
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
# ApiTommy
|
2
|
+
[](https://travis-ci.org/gatemedia/api-tommy)
|
3
|
+
|
4
|
+
ApiTommy is an opinionated little tool used to generate a wiki page documenting your APIs based on Rails/Rails-api.
|
5
|
+
|
6
|
+
Basically, you document your classes using a standard. There is no modification in your code.
|
7
|
+
You then run this tool and it will automatically generate and update your github wiki.
|
8
|
+
|
9
|
+
This tool depends on rdoc 4.2.x
|
10
|
+
|
11
|
+
# Compatibility
|
12
|
+
* rails 4.2.x
|
13
|
+
* rdoc 4.2.x
|
14
|
+
|
15
|
+
This gem is built against:
|
16
|
+
* ruby 1.9.3
|
17
|
+
* ruby 2.0.0
|
18
|
+
* ruby 2.1.3
|
19
|
+
* ruby 2.2.0
|
20
|
+
|
21
|
+
Other versions may or may not work.
|
22
|
+
|
23
|
+
## Installation
|
24
|
+
|
25
|
+
Add this line to your application's Gemfile:
|
26
|
+
|
27
|
+
gem 'api_tommy'
|
28
|
+
|
29
|
+
And then execute:
|
30
|
+
|
31
|
+
$ bundle
|
32
|
+
|
33
|
+
Or install it yourself as:
|
34
|
+
|
35
|
+
$ gem install api_tommy
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
Here is the requirements in order to have an happy tommy (pun intended):
|
40
|
+
|
41
|
+
* The best place to document your API is your controllers.
|
42
|
+
* Each class/method is documented using [TomDoc](http://tomdoc.org/).
|
43
|
+
* For the class comments, here is the usage of each [TomDoc](http://tomdoc.org/) section:
|
44
|
+
* Description: Will describe your API and the returned objects
|
45
|
+
* Returns: Not used.
|
46
|
+
* Arguments: Will describe each field of your objects
|
47
|
+
* Examples: Will provide examples of your object
|
48
|
+
* Raises: Not used.
|
49
|
+
* For the method comments, here is the usage of each [TomDoc](http://tomdoc.org/) section:
|
50
|
+
* Description: Will describe your method with its constraints. The first sentence will be used
|
51
|
+
as a title for the wiki.
|
52
|
+
* Returns: Will describe the structure returned. Is it an array? A single object?
|
53
|
+
* Arguments: Will describe each parameter accepted by the method.
|
54
|
+
* Examples: Examples of how do you call your API method.
|
55
|
+
* Raises: Will describe what exceptions can occur. Ideally, it should be http codes(eg 400, 404, ...).
|
56
|
+
* You are using Ruby 1.9.3.
|
57
|
+
* You are using Rails 3.x or 4.
|
58
|
+
* Your project is hosted on github and has a wiki.
|
59
|
+
|
60
|
+
Let's see an example. Here a really simple API documented controller:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
# This is the cars API. It provides ways to search and get cars.
|
64
|
+
# Cars are simple json objects with these fields:
|
65
|
+
#
|
66
|
+
# brand - the brand of the car
|
67
|
+
# model - the model of the car
|
68
|
+
# horsepower - the horse power of the car
|
69
|
+
# year - the year of the car
|
70
|
+
#
|
71
|
+
# Examples
|
72
|
+
#
|
73
|
+
# {
|
74
|
+
# "car": {
|
75
|
+
# "brand": "Mini",
|
76
|
+
# "model": "Cooper S",
|
77
|
+
# "horsepower": 400,
|
78
|
+
# "year": 2050
|
79
|
+
# }
|
80
|
+
# }
|
81
|
+
class CarsController < ApplicationController
|
82
|
+
|
83
|
+
# Get all cars. This method will return all available cars
|
84
|
+
#
|
85
|
+
# Examples
|
86
|
+
#
|
87
|
+
# GET /cars.json
|
88
|
+
#
|
89
|
+
# Returns all cars as an array under the `cars` field.
|
90
|
+
# Raises 500 if an error occurs
|
91
|
+
def index
|
92
|
+
render :json => Car.all
|
93
|
+
end
|
94
|
+
|
95
|
+
# Get a car. This method will return the given car's id.
|
96
|
+
#
|
97
|
+
# id - the car's id as a string.
|
98
|
+
#
|
99
|
+
# Examples
|
100
|
+
#
|
101
|
+
# GET /cars/1237.json
|
102
|
+
#
|
103
|
+
# Return the given car under the `car`field.
|
104
|
+
# Raises 404 if the car can't be found.
|
105
|
+
# Raises 500 if an error occurs
|
106
|
+
def show
|
107
|
+
render :json => Car.find(params[:id])
|
108
|
+
end
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
On the root of the project, you can then run the following command:
|
113
|
+
```
|
114
|
+
rdoc --format apitommy app/controllers/cars_controller.rb
|
115
|
+
```
|
116
|
+
|
117
|
+
This will lead to a page ```API``` in your project wiki, containing this markup:
|
118
|
+
```markdown
|
119
|
+
# Cars
|
120
|
+
|
121
|
+
This is the cars API. It provides ways to search and get cars. Cars are simple json objects with these fields:
|
122
|
+
|
123
|
+
### Fields
|
124
|
+
|
125
|
+
| Name | Description
|
126
|
+
| --- | ---
|
127
|
+
| brand | the brand of the car
|
128
|
+
| model | the model of the car
|
129
|
+
| horsepower | the horse power of the car
|
130
|
+
| year | the year of the car
|
131
|
+
|
132
|
+
### Examples
|
133
|
+
|
134
|
+
{
|
135
|
+
"car": {
|
136
|
+
"brand": "Mini",
|
137
|
+
"model": "Cooper S",
|
138
|
+
"horsepower": 400,
|
139
|
+
"year": 2050
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
## Get all cars
|
144
|
+
|
145
|
+
Get all cars. This method will return all available cars
|
146
|
+
|
147
|
+
Returns all cars as an array under the `cars` field.
|
148
|
+
|
149
|
+
### Examples
|
150
|
+
|
151
|
+
GET /cars.json
|
152
|
+
|
153
|
+
### Errors
|
154
|
+
|
155
|
+
500 if an error occurs
|
156
|
+
|
157
|
+
## Get a car
|
158
|
+
|
159
|
+
Get a car. This method will return the given car's id.
|
160
|
+
|
161
|
+
Return the given car under the `car`field.
|
162
|
+
|
163
|
+
### Parameters
|
164
|
+
|
165
|
+
| Name | Description
|
166
|
+
| --- | ---
|
167
|
+
| id | the car's id as a string.
|
168
|
+
|
169
|
+
### Examples
|
170
|
+
|
171
|
+
GET /cars/1237.json
|
172
|
+
|
173
|
+
### Errors
|
174
|
+
|
175
|
+
404 if the car can't be found.
|
176
|
+
|
177
|
+
500 if an error occurs
|
178
|
+
```
|
179
|
+
|
180
|
+
## Options
|
181
|
+
|
182
|
+
When running ```rdoc --format apitommy```, these options are available:
|
183
|
+
* ```--filename FILENAME```: the name of the wiki page. ```API``` by default.
|
184
|
+
* ```--header HEADER```: if you wish to include a header on the wiki page. Optionnal.
|
185
|
+
* ```--footer FOOTER```: if you wish to include a footer on the wiki page. Optionnal.
|
186
|
+
|
187
|
+
## Contributing
|
188
|
+
|
189
|
+
1. Fork it
|
190
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
191
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
192
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
193
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/api_tommy.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "api_tommy/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "api_tommy"
|
8
|
+
s.version = ApiTommy::VERSION
|
9
|
+
s.authors = ["David Fernandez"]
|
10
|
+
s.email = ["david.fernandez@gatemedia.ch"]
|
11
|
+
s.description = "This generator takes one or several classes with comments formatted in TomDoc and spits out a single Markdown file"
|
12
|
+
s.summary = "An API documentation generator based on RDoc and TomDoc"
|
13
|
+
s.homepage = "https://github.com/gatemedia/api-tommy"
|
14
|
+
s.license = "MIT"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split($/)
|
17
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_runtime_dependency "rdoc", "~> 4.2"
|
22
|
+
s.add_runtime_dependency "tomparse", "~> 0.4"
|
23
|
+
s.add_runtime_dependency "grit", "~> 2.5"
|
24
|
+
s.add_runtime_dependency "activesupport", "~> 4.2"
|
25
|
+
|
26
|
+
s.add_development_dependency "mocha", "~> 0.14"
|
27
|
+
s.add_development_dependency "pry", "~> 0.10"
|
28
|
+
s.add_development_dependency "minitest-reporters", "~> 1.0"
|
29
|
+
s.add_development_dependency "simplecov", "~> 0.8"
|
30
|
+
s.add_development_dependency "rake", "~> 10.4"
|
31
|
+
end
|
data/lib/api_tommy.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
require "tomparse"
|
2
|
+
|
3
|
+
module ApiTommy
|
4
|
+
class Generator
|
5
|
+
def self.setup_options(options)
|
6
|
+
options.dry_run = true
|
7
|
+
op = options.option_parser
|
8
|
+
|
9
|
+
op.on("--filename FILENAME", String, "The output filename") do |filename|
|
10
|
+
options.filename = filename.gsub(/\s+/, "-")
|
11
|
+
unless options.filename.end_with?(".md")
|
12
|
+
options.filename = "#{options.filename}.md"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
op.on("--header HEADER", String, "The header filename") do |header|
|
17
|
+
options.header = header
|
18
|
+
end
|
19
|
+
|
20
|
+
op.on("--footer FOOTER", String, "The footer filename") do |footer|
|
21
|
+
options.footer = footer
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def generate_class_doc(clazz)
|
28
|
+
generate_class_header(clazz)
|
29
|
+
clazz.instance_method_list.each { |method| generate_method_doc(method) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate_class_header(clazz)
|
33
|
+
@content << @h.h1(clazz.name.gsub(/Controller/, ""))
|
34
|
+
@tomdoc = TomParse.parse(comment(clazz).split("---").first)
|
35
|
+
@content << @h.p(@tomdoc.description)
|
36
|
+
|
37
|
+
arguments("Fields")
|
38
|
+
examples
|
39
|
+
end
|
40
|
+
|
41
|
+
def generate_method_doc(method)
|
42
|
+
@tomdoc = TomParse.parse(comment(method))
|
43
|
+
@content << @h.h2(@tomdoc.description.split(".").first)
|
44
|
+
@content << @h.p(@tomdoc.description)
|
45
|
+
|
46
|
+
returns
|
47
|
+
arguments
|
48
|
+
examples
|
49
|
+
raises
|
50
|
+
end
|
51
|
+
|
52
|
+
def arguments(title = "Parameters")
|
53
|
+
return if @tomdoc.arguments.empty?
|
54
|
+
@content << @h.h3(title)
|
55
|
+
@content << @h.th("Name", "Description")
|
56
|
+
@tomdoc.arguments.each do |a|
|
57
|
+
@content << @h.tr(a.name.to_s, a.description)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def examples
|
62
|
+
return if @tomdoc.examples.empty?
|
63
|
+
@content << @h.h3("Examples")
|
64
|
+
@tomdoc.examples.each do |e|
|
65
|
+
@content << @h.code(e.to_s)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def returns
|
70
|
+
return if @tomdoc.returns.empty?
|
71
|
+
@tomdoc.returns.each do |r|
|
72
|
+
@content << @h.p(r.to_s)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def raises
|
77
|
+
return if @tomdoc.raises.empty?
|
78
|
+
@content << @h.h3("Errors")
|
79
|
+
@tomdoc.raises.each do |r|
|
80
|
+
@content << @h.p(r.to_s.gsub(/Raises\s/, ""))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def comment(object)
|
85
|
+
result = object.comment
|
86
|
+
return result if result.is_a?(String)
|
87
|
+
result.text
|
88
|
+
end
|
89
|
+
|
90
|
+
def log(message, level = :info)
|
91
|
+
puts "[#{level}] #{message}"
|
92
|
+
end
|
93
|
+
|
94
|
+
def finalize_content
|
95
|
+
in_doc_folder do
|
96
|
+
if @options.header
|
97
|
+
@content = "#{File.read(@options.header)}\n#{@content}"
|
98
|
+
end
|
99
|
+
@content << File.read(@options.footer) if @options.footer
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def update_wiki
|
104
|
+
in_doc_folder do
|
105
|
+
if $DEBUG_RDOC
|
106
|
+
filepath = File.join(%W(doc #{@options.filename || "api_tommy.md"}))
|
107
|
+
log("Writing to local file: #{filepath}", :warning)
|
108
|
+
File.open(filepath, "w") { |f| f.write(@content) }
|
109
|
+
else
|
110
|
+
log("Updating Github wiki...")
|
111
|
+
Github.new.update_wiki(@options.filename || "API.md", @content)
|
112
|
+
end
|
113
|
+
log("Done.")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def in_doc_folder
|
118
|
+
FileUtils.cd(Dir.pwd.end_with?("/doc") ? ".." : Dir.pwd) do
|
119
|
+
yield
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Monkey patch to add accessors
|
126
|
+
# this is bad. TODO find a better way
|
127
|
+
module RDoc
|
128
|
+
class Options
|
129
|
+
attr_accessor :filename, :header, :footer
|
130
|
+
end
|
131
|
+
end
|