api_tommy 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ ruby-2.2.0
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.3
6
+ - 2.2.0
7
+ script: bundle exec rake test
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -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)
@@ -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.
@@ -0,0 +1,193 @@
1
+ # ApiTommy
2
+ [![Build Status](https://travis-ci.org/gatemedia/api-tommy.svg?branch=master)](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
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ t.pattern = 'test/**/*_test.rb'
7
+ end
@@ -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
@@ -0,0 +1,11 @@
1
+ require "rdoc/rdoc"
2
+ require "api_tommy/version"
3
+ require "api_tommy/error"
4
+ require "api_tommy/markdown"
5
+ require "api_tommy/github"
6
+ require "api_tommy/generator"
7
+
8
+ require "rdoc/generator/api_tommy"
9
+
10
+ module ApiTommy
11
+ end
@@ -0,0 +1,3 @@
1
+ module ApiTommy
2
+ Error = Class.new(StandardError)
3
+ end
@@ -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