doctor-swagger 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,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in doctor-swagger.gemspec
4
+ gemspec
@@ -0,0 +1,24 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+
17
+ # Capybara request specs
18
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
19
+
20
+ # Turnip features and steps
21
+ watch(%r{^spec/acceptance/(.+)\.feature$})
22
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
23
+ end
24
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Donald Plummer
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,29 @@
1
+ # Doctor::Swagger
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'doctor-swagger'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install doctor-swagger
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require "rspec/core/rake_task"
5
+
6
+ desc "Default: run specs."
7
+ task :default => :spec
8
+
9
+ desc "Run specs"
10
+ RSpec::Core::RakeTask.new
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), 'lib'))
3
+ puts File.expand_path(File.join(File.basename(__FILE__), 'lib'))
4
+ require 'doctor_swagger/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.authors = ["Donald Plummer", "Michael Xavier"]
8
+ gem.email = ["developers@crystalcommerce.com"]
9
+ gem.description = %q{DSL for generating swagger resource documentation}
10
+ gem.summary = <<-EOS
11
+ Provides a mixin which gives a high-level DSL for describing a swagger
12
+ resource. Use this to generate a documentation endpoint to describe an API that
13
+ you wish to document with swagger.
14
+ EOS
15
+ gem.homepage = ""
16
+
17
+ gem.files = `git ls-files`.split($\)
18
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
19
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
20
+ gem.name = "doctor-swagger"
21
+ gem.require_paths = ["lib"]
22
+ gem.version = DoctorSwagger::VERSION
23
+
24
+ gem.add_dependency("rdiscount", "~>1.6.8")
25
+
26
+ gem.add_development_dependency("rake", "~>0.9.2")
27
+ gem.add_development_dependency("rspec", "~>2.10.0")
28
+ gem.add_development_dependency("guard", "~>1.2.1")
29
+ gem.add_development_dependency("guard-rspec", "~>1.1.0")
30
+ end
@@ -0,0 +1 @@
1
+ require "doctor_swagger"
@@ -0,0 +1,78 @@
1
+ require 'doctor_swagger/endpoint'
2
+ require 'doctor_swagger/swagger_doc'
3
+ require 'doctor_swagger/error_response'
4
+ require 'doctor_swagger/errors'
5
+ require 'doctor_swagger/operation'
6
+ require 'doctor_swagger/parameter'
7
+ require 'doctor_swagger/query_parameter'
8
+ require 'doctor_swagger/post_parameter'
9
+ require 'doctor_swagger/path_parameter'
10
+ require 'doctor_swagger/post_body'
11
+ require 'doctor_swagger/root_swagger_doc'
12
+
13
+ module DoctorSwagger
14
+ #global settings, override with DSL
15
+ def self.swagger_version
16
+ @swagger_version ||= '1.0'
17
+ end
18
+
19
+ def self.api_version
20
+ @api_version ||= lambda { raise 'Set your API version with DoctorSwagger.api_version= or at the resource level'}
21
+ end
22
+
23
+ def self.base_path
24
+ @base_path ||= lambda { raise 'Set your base URL with DoctorSwagger.base_path= or at the resource level'}
25
+ end
26
+
27
+ def self.swagger_version=(version)
28
+ @swagger_version = version
29
+ end
30
+
31
+ def self.api_version=(version)
32
+ @api_version = version
33
+ end
34
+
35
+ def self.base_path=(url)
36
+ @base_path = url
37
+ end
38
+
39
+ module ClassMethods
40
+ def swagger_version(version)
41
+ @swagger_version = version
42
+ end
43
+
44
+ def api_version(version)
45
+ @api_version = version
46
+ end
47
+
48
+ def base_path(url)
49
+ @base_path = url
50
+ end
51
+
52
+ def swagger_doc
53
+ @swagger_doc
54
+ end
55
+
56
+ def swagger_resource(resource_path, &block)
57
+ @swagger_doc = SwaggerDoc.new(resource_path,
58
+ :swagger_version => @swagger_version,
59
+ :api_version => @api_version,
60
+ :base_path => @base_path,
61
+ &block)
62
+ end
63
+
64
+ def swagger_root_resource(resource_path, &block)
65
+ @swagger_doc = RootSwaggerDoc.new(resource_path,
66
+ :swagger_version => @swagger_version,
67
+ :api_version => @api_version,
68
+ :base_path => @base_path,
69
+ &block)
70
+ end
71
+ end
72
+
73
+ def self.included(receiver)
74
+ receiver.extend(ClassMethods)
75
+ end
76
+ end
77
+
78
+ require "doctor_swagger/version"
@@ -0,0 +1,32 @@
1
+ module DoctorSwagger
2
+ class Endpoint
3
+ def initialize(path, &block)
4
+ @path = path
5
+ @operations = []
6
+ instance_eval(&block)
7
+ end
8
+
9
+ def operations_as_json
10
+ if @operations && !@operations.empty?
11
+ {'operations' => @operations.map(&:as_json)}
12
+ else
13
+ {}
14
+ end
15
+ end
16
+
17
+ def as_json(*)
18
+ {
19
+ 'path' => @path,
20
+ 'description' => @description,
21
+ }.merge(operations_as_json)
22
+ end
23
+
24
+ def description(desc)
25
+ @description = desc
26
+ end
27
+
28
+ def operation(nickname, &block)
29
+ @operations << Operation.new(nickname, &block)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,15 @@
1
+ module DoctorSwagger
2
+ class ErrorResponse
3
+ def initialize(http_status, error)
4
+ @error = error
5
+ @http_status = http_status
6
+ end
7
+
8
+ def as_json(*)
9
+ {
10
+ 'error' => @error,
11
+ 'http_status' => @http_status
12
+ }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module DoctorSwagger
2
+ module Errors
3
+ def self.standard_errors
4
+ [resource_not_found, access_denied]
5
+ end
6
+
7
+ def self.resource_not_found
8
+ ErrorResponse.new(404, 'resource_not_found')
9
+ end
10
+
11
+ def self.access_denied
12
+ ErrorResponse.new(401, 'access_denied')
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,100 @@
1
+ require 'rdiscount'
2
+
3
+ module DoctorSwagger
4
+ class Operation
5
+ def initialize(nickname, &block)
6
+ @nickname = nickname
7
+ @summary = ''
8
+ @parameters = []
9
+ @error_responses = []
10
+ @embeds = []
11
+ @scopes = []
12
+ @type = ""
13
+ @internal_type = ""
14
+ instance_eval(&block)
15
+ add_embedded_parameter unless @embeds.empty?
16
+ end
17
+
18
+ def query_parameter(param, &block)
19
+ @parameters << QueryParameter.new(param, &block)
20
+ end
21
+
22
+ def path_parameter(param, &block)
23
+ @parameters << PathParameter.new(param, &block)
24
+ end
25
+
26
+ def post_parameter(param, &block)
27
+ @parameters << PostParameter.new(param, &block)
28
+ end
29
+
30
+ def post_body(&block)
31
+ @parameters << PostBody.new(&block)
32
+ end
33
+
34
+ def method(meth)
35
+ @method = meth
36
+ end
37
+
38
+ def notes(notes)
39
+ @notes = process_markdown(notes)
40
+ end
41
+
42
+ def summary(summary)
43
+ @summary = summary
44
+ end
45
+
46
+ def standard_errors
47
+ @error_responses |= Errors.standard_errors
48
+ end
49
+
50
+ def error(http_status, error)
51
+ @error_responses << ErrorResponse.new(http_status, error)
52
+ end
53
+
54
+ def embeds(*embeds)
55
+ @embeds |= embeds
56
+ end
57
+
58
+ def scopes(*scopes)
59
+ @scopes |= scopes
60
+ end
61
+
62
+ def type(type)
63
+ @type = type
64
+ end
65
+
66
+ def internal_type(internal_type)
67
+ @internal_type = internal_type
68
+ end
69
+
70
+ def as_json(*)
71
+
72
+ {
73
+ 'parameters' => @parameters.map(&:as_json),
74
+ 'httpMethod' => @method.to_s.upcase,
75
+ 'notes' => @notes,
76
+ 'embeds' => @embeds.map(&:to_s),
77
+ 'scopes' => @scopes.map(&:to_s),
78
+ 'errorResponses' => @error_responses.map(&:as_json),
79
+ 'summary' => @summary,
80
+ 'nickname' => @nickname.to_s,
81
+ 'responseClass' => @type,
82
+ 'responseTypeInternal' => @internal_type
83
+ }
84
+ end
85
+
86
+ private
87
+ def add_embedded_parameter
88
+ embeds = @embeds
89
+ query_parameter(:embedded) do
90
+ description "Optional records to embed, comma-separated"
91
+ allow_multiple! if embeds.length > 1
92
+ allowable_values(*embeds)
93
+ end
94
+ end
95
+
96
+ def process_markdown(text)
97
+ RDiscount.new(text).to_html
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,65 @@
1
+ module DoctorSwagger
2
+ class Parameter
3
+ ALLOWED_TYPES = [:string, :integer, :long, :double, :boolean]
4
+ class InvalidType < StandardError
5
+ def initialize(bad_type)
6
+ @message = "The type of '#{bad_type}' is not valid. Choose from #{ALLOWED_TYPES.inspect}"
7
+ end
8
+ end
9
+
10
+ def initialize(name, &block)
11
+ @name = name
12
+ @description = ""
13
+ @required = false
14
+ @allow_multiple = false
15
+ @allowable_values = []
16
+ @data_type = :string
17
+ instance_eval(&block)
18
+ end
19
+
20
+ def description(description)
21
+ @description = description
22
+ end
23
+
24
+ def required!
25
+ @required = true
26
+ end
27
+
28
+ def allow_multiple!
29
+ @allow_multiple = true
30
+ end
31
+
32
+ def allowable_values(*values)
33
+ @allowable_values |= values
34
+ end
35
+
36
+ def type(type)
37
+ raise InvalidType.new(type) unless ALLOWED_TYPES.include?(type)
38
+ @data_type = type
39
+ end
40
+
41
+ def allowable_values_as_json
42
+ if @allowable_values && !@allowable_values.empty?
43
+ {
44
+ 'allowableValues' => {
45
+ 'valueType' => 'LIST',
46
+ 'values' => @allowable_values.map(&:to_s)
47
+ }
48
+ }
49
+ else
50
+ {}
51
+ end
52
+ end
53
+
54
+ def as_json(*)
55
+ {
56
+ 'name' => @name.to_s,
57
+ 'description' => @description,
58
+ 'dataType' => @data_type.to_s,
59
+ 'required' => @required,
60
+ 'allowMultiple' => @allow_multiple,
61
+ 'paramType' => param_type
62
+ }.merge(allowable_values_as_json)
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,7 @@
1
+ module DoctorSwagger
2
+ class PathParameter < Parameter
3
+ def param_type
4
+ 'path'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,19 @@
1
+ module DoctorSwagger
2
+ class PostBody < PostParameter
3
+ def initialize(&block)
4
+ super(:body, &block)
5
+ end
6
+
7
+ def example(example)
8
+ @example = example
9
+ end
10
+
11
+ def as_json(*)
12
+ if @example && !@example.empty?
13
+ super.merge('example' => @example)
14
+ else
15
+ super
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ module DoctorSwagger
2
+ class PostParameter < Parameter
3
+ def param_type
4
+ 'post'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module DoctorSwagger
2
+ class QueryParameter < Parameter
3
+ def param_type
4
+ 'query'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ #TODO: specme
2
+ module DoctorSwagger
3
+ class RootSwaggerDoc < SwaggerDoc
4
+ def initialize(base_path_extension, options = {}, &block)
5
+ options[:swagger_version] ||= DoctorSwagger.swagger_version
6
+ options[:api_version] ||= DoctorSwagger.api_version
7
+ options[:base_path] ||= DoctorSwagger.base_path
8
+ @swagger_version = options[:swagger_version]
9
+ @api_version = options[:api_version]
10
+ @base_path = try_call(options[:base_path])
11
+ @base_path += base_path_extension
12
+ @endpoints = []
13
+ instance_eval(&block)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,37 @@
1
+ module DoctorSwagger
2
+ class SwaggerDoc
3
+
4
+ def initialize(resource_path, options = {}, &block)
5
+ @resource_path = resource_path
6
+ options[:swagger_version] ||= DoctorSwagger.swagger_version
7
+ options[:api_version] ||= DoctorSwagger.api_version
8
+ options[:base_path] ||= DoctorSwagger.base_path
9
+ @swagger_version = options[:swagger_version]
10
+ @api_version = options[:api_version]
11
+ @base_path = options[:base_path]
12
+ @endpoints = []
13
+ instance_eval(&block)
14
+ end
15
+
16
+ def endpoint(path, &block)
17
+ @endpoints << Endpoint.new(path, &block)
18
+ end
19
+
20
+ #TODO: add DSL for
21
+ def as_json(*)
22
+ {
23
+ 'apiVersion' => try_call(@api_version),
24
+ 'swaggerVersion' => try_call(@swagger_version),
25
+ 'basePath' => try_call(@base_path),
26
+ 'resourcePath' => @resource_path,
27
+ 'apis' => @endpoints.map(&:as_json)
28
+ }
29
+ end
30
+
31
+ private
32
+
33
+ def try_call(value)
34
+ value.respond_to?(:call) ? value.call : value
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ module DoctorSwagger
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,297 @@
1
+ require 'spec_helper'
2
+ require 'doctor-swagger'
3
+
4
+ describe DoctorSwagger do
5
+ module DoctorSwaggerTest
6
+ include DoctorSwagger
7
+
8
+ swagger_version 'some crazy version'
9
+ api_version '3.0'
10
+ base_path 'https://example.com/api'
11
+
12
+ swagger_resource '/products' do
13
+ endpoint '/products' do
14
+ description 'Products'
15
+
16
+ operation :index do
17
+ query_parameter :category_id do
18
+ description 'The category id of the products you want'
19
+ required!
20
+ type :integer
21
+ end
22
+
23
+ method :get
24
+ notes 'Returns lots of products'
25
+
26
+ type '[product]'
27
+ internal_type '[Product]'
28
+
29
+ standard_errors
30
+ error 418, "im_a_teapot"
31
+
32
+ embeds :category, :variants
33
+ scopes 'read-inventory', 'other-scope'
34
+ summary 'Find products by category id'
35
+ end
36
+ end
37
+
38
+ endpoint '/products/{product_id}' do
39
+ description 'Show product'
40
+
41
+ operation :show do
42
+ path_parameter :product_id do
43
+ description 'The product id of the product you want'
44
+ required!
45
+ type :integer
46
+ end
47
+
48
+ method :get
49
+ notes 'Returns a product'
50
+
51
+ type 'product'
52
+ internal_type 'Product'
53
+
54
+ standard_errors
55
+ embeds :category, :variants
56
+ scopes 'read-inventory', 'other-scope'
57
+ summary 'Find product by product id'
58
+ end
59
+
60
+ operation :update do
61
+ path_parameter :product_id do
62
+ description 'The product id of the product you want'
63
+ required!
64
+ type :integer
65
+ end
66
+
67
+ post_body do
68
+ description 'The JSON representation of the product'
69
+ required!
70
+
71
+ example 'product' => {
72
+ 'foo' => 'bar',
73
+ 'wat' => nil
74
+ }
75
+ end
76
+
77
+ method :put
78
+ notes <<-EOS
79
+ # Updates a *product*
80
+ EOS
81
+
82
+ type 'product'
83
+ internal_type 'Product'
84
+
85
+ standard_errors
86
+ scopes 'read-inventory', 'other-scope'
87
+ summary 'Update product by product id'
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ subject { DoctorSwaggerTest.swagger_doc }
94
+
95
+ before(:each) do
96
+ @actual = DoctorSwaggerTest.swagger_doc
97
+ end
98
+
99
+ its(:as_json) do
100
+ should == {
101
+ 'apiVersion' => '3.0',
102
+ 'swaggerVersion' => 'some crazy version',
103
+ 'basePath' => "https://example.com/api",
104
+ 'resourcePath' => '/products',
105
+ 'apis' => [
106
+ {
107
+ 'path' => '/products',
108
+ 'description' => 'Products',
109
+ 'operations' => [
110
+ {
111
+ 'parameters' => [
112
+ {
113
+ 'name' => 'category_id',
114
+ 'description' => 'The category id of the products you want',
115
+ 'dataType' => 'integer',
116
+ 'required' => true,
117
+ 'allowMultiple' => false,
118
+ 'paramType' => 'query'
119
+ },
120
+ {
121
+ 'name' => 'embedded',
122
+ 'description' => 'Optional records to embed, comma-separated',
123
+ 'dataType' => 'string',
124
+ 'required' => false,
125
+ 'allowMultiple' => true,
126
+ 'paramType' => 'query',
127
+ 'allowableValues' => {
128
+ 'values' => %w[category variants],
129
+ 'valueType' => 'LIST'
130
+ }
131
+ }
132
+ ],
133
+ 'httpMethod' => 'GET',
134
+ 'notes' => "<p>Returns lots of products</p>\n",
135
+ 'embeds' => %w[category variants],
136
+ 'scopes' => %w[read-inventory other-scope],
137
+ 'responseTypeInternal' => '[Product]',
138
+ 'responseClass' => '[product]',
139
+ 'errorResponses' => [
140
+ {
141
+ 'error' => 'resource_not_found',
142
+ 'http_status' => 404
143
+ },
144
+ {
145
+ 'error' => 'access_denied',
146
+ 'http_status' => 401
147
+ },
148
+ {
149
+ 'error' => 'im_a_teapot',
150
+ 'http_status' => 418
151
+ }
152
+ ],
153
+ 'summary' => 'Find products by category id',
154
+ 'nickname' => 'index'
155
+
156
+ }
157
+ ]
158
+ },
159
+ {
160
+ 'path' => '/products/{product_id}',
161
+ 'description' => 'Show product',
162
+ 'operations' => [
163
+ {
164
+ 'parameters' => [
165
+ {
166
+ 'name' => 'product_id',
167
+ 'description' => 'The product id of the product you want',
168
+ 'dataType' => 'integer',
169
+ 'required' => true,
170
+ 'allowMultiple' => false,
171
+ 'paramType' => 'path'
172
+ },
173
+ {
174
+ 'name' => 'embedded',
175
+ 'description' => 'Optional records to embed, comma-separated',
176
+ 'dataType' => 'string',
177
+ 'required' => false,
178
+ 'allowMultiple' => true,
179
+ 'paramType' => 'query',
180
+ 'allowableValues' => {
181
+ 'values' => %w[category variants],
182
+ 'valueType' => 'LIST'
183
+ }
184
+ }
185
+
186
+ ],
187
+ 'httpMethod' => 'GET',
188
+ 'notes' => "<p>Returns a product</p>\n",
189
+ 'embeds' => %w[category variants],
190
+ 'scopes' => %w[read-inventory other-scope],
191
+ 'responseTypeInternal' => 'Product',
192
+ 'responseClass' => 'product',
193
+ 'errorResponses' => [
194
+ {
195
+ 'error' => 'resource_not_found',
196
+ 'http_status' => 404
197
+ },
198
+ {
199
+ 'error' => 'access_denied',
200
+ 'http_status' => 401
201
+ }
202
+ ],
203
+ 'summary' => 'Find product by product id',
204
+ 'nickname' => 'show',
205
+ 'scopes' => %w[read-inventory other-scope]
206
+
207
+ },
208
+ {
209
+ 'parameters' => [
210
+ {
211
+ 'name' => 'product_id',
212
+ 'description' => 'The product id of the product you want',
213
+ 'dataType' => 'integer',
214
+ 'required' => true,
215
+ 'allowMultiple' => false,
216
+ 'paramType' => 'path'
217
+ },
218
+ {
219
+ 'name' => 'body',
220
+ 'description' => 'The JSON representation of the product',
221
+ 'dataType' => 'string',
222
+ 'required' => true,
223
+ 'allowMultiple' => false,
224
+ 'paramType' => 'post',
225
+ 'example' => {
226
+ 'product' => {
227
+ 'foo' => 'bar',
228
+ 'wat' => nil
229
+ }
230
+ }
231
+ },
232
+ ],
233
+ 'httpMethod' => 'PUT',
234
+ 'notes' => "<h1>Updates a <em>product</em></h1>\n",
235
+ 'embeds' => %w[],
236
+ 'scopes' => %w[read-inventory other-scope],
237
+ 'responseTypeInternal' => 'Product',
238
+ 'responseClass' => 'product',
239
+ 'errorResponses' => [
240
+ {
241
+ 'error' => 'resource_not_found',
242
+ 'http_status' => 404
243
+ },
244
+ {
245
+ 'error' => 'access_denied',
246
+ 'http_status' => 401
247
+ }
248
+ ],
249
+ 'summary' => 'Update product by product id',
250
+ 'nickname' => 'update',
251
+ 'scopes' => %w[read-inventory other-scope]
252
+
253
+ }
254
+ ]
255
+ }
256
+ ]
257
+ }
258
+ end
259
+
260
+ context "dynamic version/path config" do
261
+ class DynamicSwaggerResource
262
+ include DoctorSwagger
263
+
264
+
265
+ def self.prefix=(prefix)
266
+ @prefix = prefix
267
+ end
268
+
269
+ def self.format(str)
270
+ "#{@prefix}#{str}"
271
+ end
272
+
273
+ swagger_version lambda { DynamicSwaggerResource.format('some crazy version') }
274
+ api_version lambda { DynamicSwaggerResource.format('3.0') }
275
+ base_path lambda { DynamicSwaggerResource.format('https://example.com/api') }
276
+
277
+ swagger_resource '/products' do
278
+ end
279
+ end
280
+
281
+ subject { DynamicSwaggerResource.swagger_doc }
282
+
283
+ before(:each) do
284
+ DynamicSwaggerResource.prefix = '!!!'
285
+ end
286
+
287
+ its(:as_json) do
288
+ should == {
289
+ 'apiVersion' => '!!!3.0',
290
+ 'swaggerVersion' => '!!!some crazy version',
291
+ 'basePath' => "!!!https://example.com/api",
292
+ 'resourcePath' => '/products',
293
+ 'apis' => []
294
+ }
295
+ end
296
+ end
297
+ end
@@ -0,0 +1,6 @@
1
+ $: << File.join(File.basename(__FILE__), '..', 'lib')
2
+ RSpec.configure do |config|
3
+ config.treat_symbols_as_metadata_keys_with_true_values = true
4
+ config.run_all_when_everything_filtered = true
5
+ config.filter_run :focus
6
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: doctor-swagger
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Donald Plummer
9
+ - Michael Xavier
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-09-27 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rdiscount
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: 1.6.8
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: 1.6.8
31
+ - !ruby/object:Gem::Dependency
32
+ name: rake
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: 0.9.2
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: 0.9.2
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 2.10.0
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: 2.10.0
63
+ - !ruby/object:Gem::Dependency
64
+ name: guard
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ version: 1.2.1
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ~>
77
+ - !ruby/object:Gem::Version
78
+ version: 1.2.1
79
+ - !ruby/object:Gem::Dependency
80
+ name: guard-rspec
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ~>
85
+ - !ruby/object:Gem::Version
86
+ version: 1.1.0
87
+ type: :development
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ~>
93
+ - !ruby/object:Gem::Version
94
+ version: 1.1.0
95
+ description: DSL for generating swagger resource documentation
96
+ email:
97
+ - developers@crystalcommerce.com
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - .gitignore
103
+ - .rspec
104
+ - .rvmrc
105
+ - Gemfile
106
+ - Guardfile
107
+ - LICENSE
108
+ - README.md
109
+ - Rakefile
110
+ - doctor-swagger.gemspec
111
+ - lib/doctor-swagger.rb
112
+ - lib/doctor_swagger.rb
113
+ - lib/doctor_swagger/endpoint.rb
114
+ - lib/doctor_swagger/error_response.rb
115
+ - lib/doctor_swagger/errors.rb
116
+ - lib/doctor_swagger/operation.rb
117
+ - lib/doctor_swagger/parameter.rb
118
+ - lib/doctor_swagger/path_parameter.rb
119
+ - lib/doctor_swagger/post_body.rb
120
+ - lib/doctor_swagger/post_parameter.rb
121
+ - lib/doctor_swagger/query_parameter.rb
122
+ - lib/doctor_swagger/root_swagger_doc.rb
123
+ - lib/doctor_swagger/swagger_doc.rb
124
+ - lib/doctor_swagger/version.rb
125
+ - spec/doctor_swagger_spec.rb
126
+ - spec/spec_helper.rb
127
+ homepage: ''
128
+ licenses: []
129
+ post_install_message:
130
+ rdoc_options: []
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ! '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ required_rubygems_version: !ruby/object:Gem::Requirement
140
+ none: false
141
+ requirements:
142
+ - - ! '>='
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubyforge_project:
147
+ rubygems_version: 1.8.24
148
+ signing_key:
149
+ specification_version: 3
150
+ summary: Provides a mixin which gives a high-level DSL for describing a swagger resource.
151
+ Use this to generate a documentation endpoint to describe an API that you wish to
152
+ document with swagger.
153
+ test_files:
154
+ - spec/doctor_swagger_spec.rb
155
+ - spec/spec_helper.rb
156
+ has_rdoc: