grape-slate 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.rubocop.yml +18 -0
- data/.travis.yml +10 -0
- data/Gemfile +8 -0
- data/Guardfile +12 -0
- data/LICENSE.txt +22 -0
- data/README.md +89 -0
- data/Rakefile +23 -0
- data/grape-slate.gemspec +32 -0
- data/lib/grape-slate.rb +24 -0
- data/lib/grape-slate/config.rb +62 -0
- data/lib/grape-slate/document.rb +78 -0
- data/lib/grape-slate/sample_generator.rb +45 -0
- data/lib/grape-slate/templates/document.md.erb +44 -0
- data/lib/grape-slate/templates/properties.md.erb +7 -0
- data/lib/grape-slate/templates/sample.md +214 -0
- data/lib/grape-slate/version.rb +3 -0
- data/lib/grape/slate.rb +1 -0
- data/spec/grape-slate/document_spec.rb +56 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/support/config_context.rb +13 -0
- data/spec/support/sample_api.rb +38 -0
- metadata +213 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5e5f0ec63333f2ed9755fbd1a9e739f255c37857
|
4
|
+
data.tar.gz: 1ea43b80a15189cc8f4206ccc9106be2768dffbc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e91a4c1503f278fb21f166c9776d46da546dadfb0f7bc2a5c03b0a06cd26630eea431fb1483c614bba7304cc6f4b823e868231c4d9029e2678107d50752ab36f
|
7
|
+
data.tar.gz: 54d8ced9b41b87f6d82d9160b3b4849b757bb56671054a48d5321abfe29afe43a1ededab84469e0c7abc794c86faacbefbbf230b1f1d824227046a1a3209a168
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
AllCops:
|
2
|
+
Excludes:
|
3
|
+
- Rakefile
|
4
|
+
- vendor/**
|
5
|
+
- bin/**
|
6
|
+
|
7
|
+
Documentation:
|
8
|
+
# don't require classes to be documented
|
9
|
+
Enabled: false
|
10
|
+
|
11
|
+
Encoding:
|
12
|
+
# no need to always specify encoding
|
13
|
+
Enabled: false
|
14
|
+
|
15
|
+
LineLength:
|
16
|
+
# just one more character please
|
17
|
+
Max: 80
|
18
|
+
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# More info at https://github.com/guard/guard#readme
|
2
|
+
|
3
|
+
guard 'rspec', :version => 2 do
|
4
|
+
watch(%r{^spec/.+_spec\.rb$})
|
5
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
6
|
+
watch('spec/spec_helper.rb') { "spec/" }
|
7
|
+
end
|
8
|
+
|
9
|
+
guard 'bundler' do
|
10
|
+
watch('Gemfile')
|
11
|
+
watch(/^.+\.gemspec/)
|
12
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 John Allen
|
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,89 @@
|
|
1
|
+
# GrapeSlate
|
2
|
+
|
3
|
+
[![Code Climate](https://codeclimate.com/github/connexio-labs/grape-slate.png)](https://codeclimate.com/github/connexio-labs/grape-slate)
|
4
|
+
[![Build Status](https://travis-ci.org/connexio-labs/grape-slate.png?branch=master)](https://travis-ci.org/connexio-labs/grape-slate)
|
5
|
+
[![Coverage Status](https://coveralls.io/repos/connexio-labs/grape-slate/badge.png)](https://coveralls.io/r/connexio-labs/grape-slate)
|
6
|
+
[![Dependency Status](https://gemnasium.com/connexio-labs/grape-slate.png)](https://gemnasium.com/connexio-labs/grape-slate)
|
7
|
+
[![Gem Version](https://badge.fury.io/rb/grape-slate.png)](http://badge.fury.io/rb/grape-slate)
|
8
|
+
|
9
|
+
Auto generates an [Slate Document](https://github.com/tripit/slate) from the docuementation that is created by your [Grape](https://github.com/intridea/grape) API.
|
10
|
+
|
11
|
+
### NOTE
|
12
|
+
|
13
|
+
This is an early implementation that makes some assumptions about your API (follows a standard REST pattern) that works with our implementation of Grape API's. There is a new an [unreleased feature in Grape](https://github.com/intridea/grape#parameter-documentation) that allows for appending additional documentation. This project is dependent on this feature in order to create example JSON requests and responses.
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
Add this line to your application's Gemfile:
|
18
|
+
|
19
|
+
gem 'grape', github: 'intridea/grape' # see note above
|
20
|
+
gem 'grape-slate'
|
21
|
+
|
22
|
+
And then execute:
|
23
|
+
|
24
|
+
$ bundle
|
25
|
+
|
26
|
+
Or install it yourself as:
|
27
|
+
|
28
|
+
$ gem install grape-slate
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
Add some metadata about your API and then execute the `generate` method on the `GrapeSlate::Blueprint` class.
|
33
|
+
|
34
|
+
### Configuration
|
35
|
+
|
36
|
+
Configure details about your api in an initializers or similar:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
GrapeSlate.config do |config|
|
40
|
+
# the name of your api
|
41
|
+
config.name = 'Awesome API'
|
42
|
+
# a description for your api
|
43
|
+
config.description = 'The awesome description'
|
44
|
+
# the type to use for generated sample id's (`integer` or `uuid`)
|
45
|
+
config.example_id_type = :uuid
|
46
|
+
# resources you do not want documented
|
47
|
+
config.resource_exclusion = [:admin, :swagger_doc]
|
48
|
+
# whether or not examples should include a root element (default: false)
|
49
|
+
config.include_root = true
|
50
|
+
end
|
51
|
+
|
52
|
+
# request headers you want documented
|
53
|
+
GrapeSlate.config.request_headers = [
|
54
|
+
{ 'Accept-Charset' => 'utf-8' },
|
55
|
+
{ 'Connection' => 'keep-alive' }
|
56
|
+
]
|
57
|
+
|
58
|
+
# response headers you want documented
|
59
|
+
GrapeSlate.config.response_headers = [
|
60
|
+
{ 'Content-Length' => '21685' },
|
61
|
+
{ 'Connection' => 'keep-alive' }
|
62
|
+
]
|
63
|
+
```
|
64
|
+
|
65
|
+
### Generation
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
# supply the class you'd like to document and generate your blueprint
|
69
|
+
GrapeSlate::Blueprint.new(AwesomeAPI).generate
|
70
|
+
```
|
71
|
+
|
72
|
+
## TODO
|
73
|
+
|
74
|
+
* Add a rake task to simplify generation
|
75
|
+
* ~~Add support for listing all of a resources attributes at the resource level as a markdown table~~
|
76
|
+
* Handle ever changing sample id's (don't want git diff's after every generation)
|
77
|
+
* Add option to change or remove the sample id field (eg. `_id` vs `id`)
|
78
|
+
* What if someone does not use JSON?!?
|
79
|
+
* ~~Create sample response for list endpoints (array)~~
|
80
|
+
* Add support for writing the blueprint to disk
|
81
|
+
* Add an option to include root in json
|
82
|
+
|
83
|
+
## Contributing
|
84
|
+
|
85
|
+
1. Fork it ( http://github.com/connexio-labs/grape-slate/fork )
|
86
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
87
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
88
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
89
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.setup :default, :test, :development
|
4
|
+
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
7
|
+
require 'rspec/core/rake_task'
|
8
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
9
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'rainbow/ext/string' unless String.respond_to?(:color)
|
13
|
+
require 'rubocop/rake_task'
|
14
|
+
Rubocop::RakeTask.new(:rubocop)
|
15
|
+
|
16
|
+
task default: [:rubocop, :spec]
|
17
|
+
|
18
|
+
task :console do
|
19
|
+
require 'pry'
|
20
|
+
require 'grape-slate'
|
21
|
+
ARGV.clear
|
22
|
+
Pry.start
|
23
|
+
end
|
data/grape-slate.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'grape-slate/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'grape-slate'
|
8
|
+
spec.version = GrapeSlate::VERSION
|
9
|
+
spec.authors = ['John Allen']
|
10
|
+
spec.email = ['john@threedogconsulting.com']
|
11
|
+
spec.summary = %q{Allows for generating a Slate document for your Grape API}
|
12
|
+
spec.description = %q{Auto generates a Slate (https://github.com/tripit/slate) document from the docuementation that is created by your Grape API}
|
13
|
+
spec.homepage = 'https://github.com/connexio-labs/grape-slate'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_runtime_dependency 'grape-markdown', '~> 0.0'
|
22
|
+
|
23
|
+
spec.add_development_dependency 'coveralls', '~> 0.7'
|
24
|
+
spec.add_development_dependency 'rspec', '~> 2.14'
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.5'
|
26
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
27
|
+
spec.add_development_dependency 'rubocop', '~> 0.18'
|
28
|
+
spec.add_development_dependency 'pry', '~> 0.9'
|
29
|
+
spec.add_development_dependency 'guard', '~> 2.4'
|
30
|
+
spec.add_development_dependency 'guard-rspec', '~> 4.2'
|
31
|
+
spec.add_development_dependency 'guard-bundler', '~> 2.0'
|
32
|
+
end
|
data/lib/grape-slate.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'grape-markdown'
|
2
|
+
|
3
|
+
module GrapeSlate
|
4
|
+
autoload :Version, 'grape-slate/version'
|
5
|
+
autoload :Config, 'grape-slate/config'
|
6
|
+
autoload :SampleGenerator, 'grape-slate/sample_generator'
|
7
|
+
autoload :Document, 'grape-slate/document'
|
8
|
+
|
9
|
+
def self.config
|
10
|
+
block_given? ? yield(Config) : Config
|
11
|
+
end
|
12
|
+
|
13
|
+
class UnsupportedIDType < StandardError
|
14
|
+
def message
|
15
|
+
'Unsupported id type, supported types are [integer, uuid, bson]'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class BSONNotDefinied < StandardError
|
20
|
+
def message
|
21
|
+
'BSON type id requested but bson library is not present'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module GrapeSlate
|
2
|
+
class Config
|
3
|
+
SETTINGS = [
|
4
|
+
:name,
|
5
|
+
:description,
|
6
|
+
:request_headers,
|
7
|
+
:response_headers,
|
8
|
+
:example_id_type,
|
9
|
+
:resource_exclusion,
|
10
|
+
:include_root
|
11
|
+
]
|
12
|
+
|
13
|
+
class << self
|
14
|
+
attr_accessor(*SETTINGS)
|
15
|
+
|
16
|
+
def request_headers
|
17
|
+
@request_headers ||= []
|
18
|
+
end
|
19
|
+
|
20
|
+
def response_headers
|
21
|
+
@response_headers ||= []
|
22
|
+
end
|
23
|
+
|
24
|
+
def resource_exclusion
|
25
|
+
@resource_exclusion ||= []
|
26
|
+
end
|
27
|
+
|
28
|
+
def include_root
|
29
|
+
@include_root ||= false
|
30
|
+
end
|
31
|
+
|
32
|
+
def supported_id_types
|
33
|
+
[:integer, :uuid, :bson]
|
34
|
+
end
|
35
|
+
|
36
|
+
def example_id_type=(value)
|
37
|
+
fail UnsupportedIDType unless supported_id_types.include?(value)
|
38
|
+
|
39
|
+
if value.to_sym == :bson && !Object.const_defined?('BSON')
|
40
|
+
fail BSONNotDefinied
|
41
|
+
end
|
42
|
+
|
43
|
+
@example_id_type = value
|
44
|
+
end
|
45
|
+
|
46
|
+
def example_id_type
|
47
|
+
@example_id_type ||= :integer
|
48
|
+
end
|
49
|
+
|
50
|
+
def generate_id
|
51
|
+
case example_id_type
|
52
|
+
when :integer
|
53
|
+
SecureRandom.random_number(1000)
|
54
|
+
when :uuid
|
55
|
+
SecureRandom.uuid
|
56
|
+
when :bson
|
57
|
+
BSON::ObjectId.new.to_s
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module GrapeSlate
|
2
|
+
class Document < GrapeMarkdown::Document
|
3
|
+
attr_reader :api_class, :document_template, :properties_template
|
4
|
+
|
5
|
+
delegate(*GrapeMarkdown::Config::SETTINGS, to: 'GrapeSlate::Config')
|
6
|
+
|
7
|
+
def initialize(api_class)
|
8
|
+
@api_class = api_class
|
9
|
+
@document_template = template_for(:document)
|
10
|
+
@properties_template = template_for(:properties)
|
11
|
+
end
|
12
|
+
|
13
|
+
def generate
|
14
|
+
ERB.new(document_template, nil, '-').result(binding)
|
15
|
+
end
|
16
|
+
|
17
|
+
def write
|
18
|
+
fail 'Not yet supported'
|
19
|
+
end
|
20
|
+
|
21
|
+
def routes
|
22
|
+
@routes ||= api_class.routes.map do |route|
|
23
|
+
GrapeMarkdown::Route.new(route)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def resources
|
28
|
+
@resources ||= begin
|
29
|
+
grouped_routes = routes.group_by(&:route_name).reject do |name, routes|
|
30
|
+
resource_exclusion.include?(name.to_sym)
|
31
|
+
end
|
32
|
+
|
33
|
+
grouped_routes.map do |name, routes|
|
34
|
+
GrapeMarkdown::Resource.new(name, routes)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def properties_table(resource)
|
40
|
+
ERB.new(properties_template, nil, '-').result(resource.resource_binding)
|
41
|
+
end
|
42
|
+
|
43
|
+
def formatted_request_headers
|
44
|
+
formatted_headers(GrapeSlate::Config.request_headers)
|
45
|
+
end
|
46
|
+
|
47
|
+
def formatted_response_headers
|
48
|
+
formatted_headers(GrapeSlate::Config.response_headers)
|
49
|
+
end
|
50
|
+
|
51
|
+
def show_request_sample?(route)
|
52
|
+
%w(PUT POST).include?(route.route_method)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def template_for(name)
|
58
|
+
directory = File.dirname(File.expand_path(__FILE__))
|
59
|
+
path = File.join(directory, "./templates/#{name}.md.erb")
|
60
|
+
|
61
|
+
File.read(path)
|
62
|
+
end
|
63
|
+
|
64
|
+
def formatted_headers(headers)
|
65
|
+
return '' unless headers.present?
|
66
|
+
|
67
|
+
spacer = "\n" + (' ' * 12)
|
68
|
+
|
69
|
+
strings = headers.map do |header|
|
70
|
+
key, value = *header.first
|
71
|
+
|
72
|
+
"#{key}: #{value}"
|
73
|
+
end
|
74
|
+
|
75
|
+
" + Headers\n" + spacer + strings.join(spacer)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module GrapeSlate
|
2
|
+
class SampleGenerator
|
3
|
+
attr_reader :resource, :root
|
4
|
+
|
5
|
+
delegate :unique_params, to: :resource
|
6
|
+
|
7
|
+
def initialize(resource)
|
8
|
+
@resource = resource
|
9
|
+
@root = resource.key.singularize
|
10
|
+
end
|
11
|
+
|
12
|
+
def sample(id = false)
|
13
|
+
array = resource.unique_params.map do |param|
|
14
|
+
next if param.name == root
|
15
|
+
|
16
|
+
[param.name, param.example]
|
17
|
+
end
|
18
|
+
|
19
|
+
hash = Hash[array.compact]
|
20
|
+
|
21
|
+
hash = hash.reverse_merge(id: Config.generate_id) if id
|
22
|
+
hash = { root => hash } if Config.include_root
|
23
|
+
|
24
|
+
hash
|
25
|
+
end
|
26
|
+
|
27
|
+
def request
|
28
|
+
hash = sample
|
29
|
+
|
30
|
+
return unless hash.present?
|
31
|
+
|
32
|
+
JSON.pretty_generate(hash)
|
33
|
+
end
|
34
|
+
|
35
|
+
def response(list = false)
|
36
|
+
hash = sample(true)
|
37
|
+
|
38
|
+
return unless hash.present?
|
39
|
+
|
40
|
+
hash = [hash] if list
|
41
|
+
|
42
|
+
JSON.pretty_generate(hash)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
---
|
2
|
+
title: <%= name %> Reference
|
3
|
+
|
4
|
+
language_tabs:
|
5
|
+
- shell
|
6
|
+
|
7
|
+
toc_footers:
|
8
|
+
- <a href='#'>Sign Up for a Developer Key</a>
|
9
|
+
---
|
10
|
+
|
11
|
+
# <%= name %>
|
12
|
+
|
13
|
+
<%= description %>
|
14
|
+
|
15
|
+
<% resources.each do |resource| %>
|
16
|
+
# <%= resource.title %>
|
17
|
+
<% resource.namespaced.each do |grouped_resource| %>
|
18
|
+
<% grouped_resource.paths.each do |resource_by_path| %>
|
19
|
+
<% resource_by_path.routes.each do |route| %>
|
20
|
+
## <%= route.route_description %>
|
21
|
+
|
22
|
+
```shell
|
23
|
+
curl http://example.com
|
24
|
+
```
|
25
|
+
|
26
|
+
> The above command returns JSON structured like this:
|
27
|
+
|
28
|
+
```json
|
29
|
+
<%= resource.sample_response(route) %>
|
30
|
+
```
|
31
|
+
<%= route.route_description %>
|
32
|
+
|
33
|
+
### HTTP Request
|
34
|
+
|
35
|
+
`<%= route.route_method %>`
|
36
|
+
|
37
|
+
### URL Parameters
|
38
|
+
|
39
|
+
<%= properties_table(resource) %>
|
40
|
+
|
41
|
+
<% end %>
|
42
|
+
<% end %>
|
43
|
+
<% end %>
|
44
|
+
<% end %>
|
@@ -0,0 +1,214 @@
|
|
1
|
+
---
|
2
|
+
title: API Reference
|
3
|
+
|
4
|
+
language_tabs:
|
5
|
+
- shell
|
6
|
+
- ruby
|
7
|
+
- python
|
8
|
+
|
9
|
+
toc_footers:
|
10
|
+
- <a href='#'>Sign Up for a Developer Key</a>
|
11
|
+
- <a href='http://github.com/tripit/slate'>Documentation Powered by Slate</a>
|
12
|
+
---
|
13
|
+
|
14
|
+
# Introduction
|
15
|
+
|
16
|
+
Welcome to the Kittn API! You can use our API to access Kittn API endpoints, which can get information on various cats, kittens, and breeds in our database.
|
17
|
+
|
18
|
+
We have language bindings in Shell, Ruby, and Python! You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.
|
19
|
+
|
20
|
+
This example API documentation page was created with [Slate](http://github.com/tripit/slate). Feel free to edit it and use it as a base for your own API's documentation.
|
21
|
+
|
22
|
+
# Authentication
|
23
|
+
|
24
|
+
> To authorize, use this code:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
require 'kittn'
|
28
|
+
|
29
|
+
api = Kittn::APIClient.authorize!('meowmeowmeow')
|
30
|
+
```
|
31
|
+
|
32
|
+
```python
|
33
|
+
import 'kittn'
|
34
|
+
|
35
|
+
api = Kittn.authorize('meowmeowmeow')
|
36
|
+
```
|
37
|
+
|
38
|
+
```shell
|
39
|
+
# With shell, you can just pass the correct header with each request
|
40
|
+
curl "api_endpoint_here"
|
41
|
+
-H "Authorization: meowmeowmeow"
|
42
|
+
```
|
43
|
+
|
44
|
+
> Make sure to replace `meowmeowmeow` with your API key.
|
45
|
+
|
46
|
+
Kittn uses API keys to allow access to the API. You can register a new Kittn API key at our [developer portal](http://example.com/developers).
|
47
|
+
|
48
|
+
Kittn expects for the API key to be included in all API requests to the server in a header that looks like the following:
|
49
|
+
|
50
|
+
`Authorization: meowmeowmeow`
|
51
|
+
|
52
|
+
<aside class="notice">
|
53
|
+
You must replace `meowmeowmeow` with your personal API key.
|
54
|
+
</aside>
|
55
|
+
|
56
|
+
# Kittens
|
57
|
+
|
58
|
+
## Get All Kittens
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
require 'kittn'
|
62
|
+
|
63
|
+
api = Kittn::APIClient.authorize!('meowmeowmeow')
|
64
|
+
api.kittens.get
|
65
|
+
```
|
66
|
+
|
67
|
+
```python
|
68
|
+
import 'kittn'
|
69
|
+
|
70
|
+
api = Kittn.authorize('meowmeowmeow')
|
71
|
+
api.kittens.get()
|
72
|
+
```
|
73
|
+
|
74
|
+
```shell
|
75
|
+
curl "http://example.com/api/kittens"
|
76
|
+
-H "Authorization: meowmeowmeow"
|
77
|
+
```
|
78
|
+
|
79
|
+
> The above command returns JSON structured like this:
|
80
|
+
|
81
|
+
```json
|
82
|
+
[
|
83
|
+
{
|
84
|
+
"id": 1,
|
85
|
+
"name": "Fluffums",
|
86
|
+
"breed": "calico",
|
87
|
+
"fluffiness": 6,
|
88
|
+
"cuteness": 7
|
89
|
+
},
|
90
|
+
{
|
91
|
+
"id": 2,
|
92
|
+
"name": "Isis",
|
93
|
+
"breed": "unknown",
|
94
|
+
"fluffiness": 5,
|
95
|
+
"cuteness": 10
|
96
|
+
}
|
97
|
+
]
|
98
|
+
```
|
99
|
+
|
100
|
+
This endpoint retrieves all kittens.
|
101
|
+
|
102
|
+
### HTTP Request
|
103
|
+
|
104
|
+
`GET http://example.com/kittens`
|
105
|
+
|
106
|
+
### Query Parameters
|
107
|
+
|
108
|
+
Parameter | Default | Description
|
109
|
+
--------- | ------- | -----------
|
110
|
+
include_cats | false | If set to true, the result will also include cats.
|
111
|
+
available | true | If set to false, the result will include kittens that have already been adopted.
|
112
|
+
|
113
|
+
<aside class="success">
|
114
|
+
Remember — a happy kitten is an authenticated kitten!
|
115
|
+
</aside>
|
116
|
+
|
117
|
+
## Get a Specific Kitten
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
require 'kittn'
|
121
|
+
|
122
|
+
api = Kittn::APIClient.authorize!('meowmeowmeow')
|
123
|
+
api.kittens.get(2)
|
124
|
+
```
|
125
|
+
|
126
|
+
```python
|
127
|
+
import 'kittn'
|
128
|
+
|
129
|
+
api = Kittn.authorize('meowmeowmeow')
|
130
|
+
api.kittens.get(2)
|
131
|
+
```
|
132
|
+
|
133
|
+
```shell
|
134
|
+
curl "http://example.com/api/kittens/3"
|
135
|
+
-H "Authorization: meowmeowmeow"
|
136
|
+
```
|
137
|
+
|
138
|
+
> The above command returns JSON structured like this:
|
139
|
+
|
140
|
+
```json
|
141
|
+
{
|
142
|
+
"id": 2,
|
143
|
+
"name": "Isis",
|
144
|
+
"breed": "unknown",
|
145
|
+
"fluffiness": 5,
|
146
|
+
"cuteness": 10
|
147
|
+
}
|
148
|
+
```
|
149
|
+
|
150
|
+
This endpoint retrieves a specific kitten.
|
151
|
+
|
152
|
+
<aside class="warning">If you're not using an administrator API key, note that some kittens will return 403 Forbidden if they are hidden for admins only.</aside>
|
153
|
+
|
154
|
+
### HTTP Request
|
155
|
+
|
156
|
+
`GET http://example.com/kittens/<ID>`
|
157
|
+
|
158
|
+
### URL Parameters
|
159
|
+
|
160
|
+
Parameter | Description
|
161
|
+
--------- | -----------
|
162
|
+
ID | The ID of the cat to retrieve
|
163
|
+
|
164
|
+
# Errors
|
165
|
+
|
166
|
+
The Kittn API uses the following error codes:
|
167
|
+
|
168
|
+
|
169
|
+
Error Code | Meaning
|
170
|
+
---------- | -------
|
171
|
+
400 | Bad Request -- Your request sucks
|
172
|
+
401 | Unauthorized -- Your API key is wrong
|
173
|
+
403 | Forbidden -- The kitten requested is hidden for administrators only
|
174
|
+
404 | Not Found -- The specified kitten could not be found
|
175
|
+
405 | Method Not Allowed -- You tried to access a kitten with an invalid method
|
176
|
+
406 | Not Acceptable -- You requested a format that isn't json
|
177
|
+
410 | Gone -- The kitten requested has been removed from our servers
|
178
|
+
418 | I'm a teapot
|
179
|
+
429 | Too Many Requests -- You're requesting too many kittens! Slown down!
|
180
|
+
500 | Internal Server Error -- We had a problem with our server. Try again later.
|
181
|
+
503 | Service Unavailable -- We're temporarially offline for maintanance. Please try again later.
|
182
|
+
|
183
|
+
|
184
|
+
|
185
|
+
|
186
|
+
<%= properties_table(resource) %>
|
187
|
+
<% resource.namespaced.each do |grouped_resource| %>
|
188
|
+
<% grouped_resource.paths.each do |resource_by_path| %>
|
189
|
+
## <%= resource_by_path.header %>
|
190
|
+
Actions on the <%= resource.name %> resource
|
191
|
+
<% if resource_by_path.routes.first.route_params.present? %>
|
192
|
+
+ Parameters
|
193
|
+
<% resource_by_path.routes.first.route_params.each do |param| %>
|
194
|
+
+ <%= param.description %>
|
195
|
+
<% end %>
|
196
|
+
<% end %>
|
197
|
+
<% resource_by_path.routes.each do |route| %>
|
198
|
+
### <%= route.route_description %>
|
199
|
+
<% if show_request_sample?(route) %>
|
200
|
+
<%= route.request_description %>
|
201
|
+
<%= formatted_request_headers %>
|
202
|
+
+ Body
|
203
|
+
|
204
|
+
<%= resource.sample_request %>
|
205
|
+
<% end %>
|
206
|
+
<%= route.response_description %>
|
207
|
+
<%= formatted_response_headers %>
|
208
|
+
|
209
|
+
+ Body
|
210
|
+
|
211
|
+
<%= resource.sample_response(route) %>
|
212
|
+
<% end %>
|
213
|
+
<% end %>
|
214
|
+
<% end %>
|
data/lib/grape/slate.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'grape-slate'
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GrapeSlate::Document do
|
4
|
+
include_context 'configuration'
|
5
|
+
|
6
|
+
before do
|
7
|
+
GrapeSlate.config do |config|
|
8
|
+
config.name = name
|
9
|
+
config.description = description
|
10
|
+
config.resource_exclusion = [:admin]
|
11
|
+
end
|
12
|
+
|
13
|
+
GrapeSlate.config.request_headers = [
|
14
|
+
{ 'Accept-Charset' => 'utf-8' },
|
15
|
+
{ 'Connection' => 'keep-alive' }
|
16
|
+
]
|
17
|
+
|
18
|
+
GrapeSlate.config.response_headers = [
|
19
|
+
{ 'Content-Length' => '21685' },
|
20
|
+
{ 'Connection' => 'keep-alive' }
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
subject { GrapeSlate::Document.new(SampleApi) }
|
25
|
+
|
26
|
+
context '#generate' do
|
27
|
+
let(:klass) { SampleApi }
|
28
|
+
|
29
|
+
subject { GrapeSlate::Document.new(klass).generate }
|
30
|
+
|
31
|
+
it 'sets the title based on name' do
|
32
|
+
puts subject
|
33
|
+
expect(subject).to include("title: #{name} Reference")
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'lists shell as the language type' do
|
37
|
+
expect(subject).to include(' - shell')
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'creates a header from configuration' do
|
41
|
+
expect(subject).to include("# #{name}")
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'adds the description' do
|
45
|
+
expect(subject).to include(description)
|
46
|
+
end
|
47
|
+
|
48
|
+
# it 'includes groups for each resource' do
|
49
|
+
# expect(subject).to include('# Group Widgets')
|
50
|
+
# end
|
51
|
+
|
52
|
+
# it 'includes properties for the resources' do
|
53
|
+
# expect(subject).to include('Properties')
|
54
|
+
# end
|
55
|
+
end
|
56
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'support'))
|
4
|
+
|
5
|
+
require 'grape/slate'
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
require 'bundler'
|
9
|
+
Bundler.setup :default, :test
|
10
|
+
|
11
|
+
require 'coveralls'
|
12
|
+
Coveralls.wear!
|
13
|
+
|
14
|
+
require 'rspec'
|
15
|
+
require 'pry'
|
16
|
+
|
17
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
@@ -0,0 +1,13 @@
|
|
1
|
+
shared_context 'configuration' do
|
2
|
+
let(:name) { 'some api v1' }
|
3
|
+
let(:description) { 'some blueprint description' }
|
4
|
+
let(:resource_exclusion) { [:admin, :swagger_docs] }
|
5
|
+
|
6
|
+
let(:request_headers) do
|
7
|
+
[{ 'Accept-Charset' => 'utf-8' }]
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:response_headers) do
|
11
|
+
[{ 'Connection' => 'keep-alive' }]
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class SampleApi < Grape::API
|
2
|
+
resource 'widgets' do
|
3
|
+
desc 'widgets list'
|
4
|
+
get '/' do
|
5
|
+
end
|
6
|
+
|
7
|
+
desc 'individual widget'
|
8
|
+
get ':id' do
|
9
|
+
end
|
10
|
+
|
11
|
+
desc 'create a widget'
|
12
|
+
params do
|
13
|
+
requires :name,
|
14
|
+
type: 'string',
|
15
|
+
desc: 'the widgets name',
|
16
|
+
documentation: { example: 'super widget' }
|
17
|
+
optional :description,
|
18
|
+
type: 'string',
|
19
|
+
desc: 'the widgets name',
|
20
|
+
documentation: { example: 'the best widget ever made' }
|
21
|
+
end
|
22
|
+
post '/' do
|
23
|
+
end
|
24
|
+
|
25
|
+
desc 'update a widget'
|
26
|
+
params do
|
27
|
+
optional :name, type: 'string', desc: 'the widgets name'
|
28
|
+
optional :description, type: 'string', desc: 'the widgets name'
|
29
|
+
end
|
30
|
+
put ':id' do
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
resource 'admin' do
|
35
|
+
get '/' do
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: grape-slate
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- John Allen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: grape-markdown
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: coveralls
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.7'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.14'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.14'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.5'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.5'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.18'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.18'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.9'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.9'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: guard
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '2.4'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '2.4'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: guard-rspec
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '4.2'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '4.2'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: guard-bundler
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '2.0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '2.0'
|
153
|
+
description: Auto generates a Slate (https://github.com/tripit/slate) document from
|
154
|
+
the docuementation that is created by your Grape API
|
155
|
+
email:
|
156
|
+
- john@threedogconsulting.com
|
157
|
+
executables: []
|
158
|
+
extensions: []
|
159
|
+
extra_rdoc_files: []
|
160
|
+
files:
|
161
|
+
- ".gitignore"
|
162
|
+
- ".rspec"
|
163
|
+
- ".rubocop.yml"
|
164
|
+
- ".travis.yml"
|
165
|
+
- Gemfile
|
166
|
+
- Guardfile
|
167
|
+
- LICENSE.txt
|
168
|
+
- README.md
|
169
|
+
- Rakefile
|
170
|
+
- grape-slate.gemspec
|
171
|
+
- lib/grape-slate.rb
|
172
|
+
- lib/grape-slate/config.rb
|
173
|
+
- lib/grape-slate/document.rb
|
174
|
+
- lib/grape-slate/sample_generator.rb
|
175
|
+
- lib/grape-slate/templates/document.md.erb
|
176
|
+
- lib/grape-slate/templates/properties.md.erb
|
177
|
+
- lib/grape-slate/templates/sample.md
|
178
|
+
- lib/grape-slate/version.rb
|
179
|
+
- lib/grape/slate.rb
|
180
|
+
- spec/grape-slate/document_spec.rb
|
181
|
+
- spec/spec_helper.rb
|
182
|
+
- spec/support/config_context.rb
|
183
|
+
- spec/support/sample_api.rb
|
184
|
+
homepage: https://github.com/connexio-labs/grape-slate
|
185
|
+
licenses:
|
186
|
+
- MIT
|
187
|
+
metadata: {}
|
188
|
+
post_install_message:
|
189
|
+
rdoc_options: []
|
190
|
+
require_paths:
|
191
|
+
- lib
|
192
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
193
|
+
requirements:
|
194
|
+
- - ">="
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
version: '0'
|
197
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - ">="
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
requirements: []
|
203
|
+
rubyforge_project:
|
204
|
+
rubygems_version: 2.2.2
|
205
|
+
signing_key:
|
206
|
+
specification_version: 4
|
207
|
+
summary: Allows for generating a Slate document for your Grape API
|
208
|
+
test_files:
|
209
|
+
- spec/grape-slate/document_spec.rb
|
210
|
+
- spec/spec_helper.rb
|
211
|
+
- spec/support/config_context.rb
|
212
|
+
- spec/support/sample_api.rb
|
213
|
+
has_rdoc:
|