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.
@@ -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