swaggard 0.0.4

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.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +178 -0
  4. data/Rakefile +24 -0
  5. data/app/assets/fonts/swaggard/droid-sans-v6-latin-700.eot +0 -0
  6. data/app/assets/fonts/swaggard/droid-sans-v6-latin-700.svg +411 -0
  7. data/app/assets/fonts/swaggard/droid-sans-v6-latin-700.ttf +0 -0
  8. data/app/assets/fonts/swaggard/droid-sans-v6-latin-700.woff +0 -0
  9. data/app/assets/fonts/swaggard/droid-sans-v6-latin-700.woff2 +0 -0
  10. data/app/assets/fonts/swaggard/droid-sans-v6-latin-regular.eot +0 -0
  11. data/app/assets/fonts/swaggard/droid-sans-v6-latin-regular.svg +403 -0
  12. data/app/assets/fonts/swaggard/droid-sans-v6-latin-regular.ttf +0 -0
  13. data/app/assets/fonts/swaggard/droid-sans-v6-latin-regular.woff +0 -0
  14. data/app/assets/fonts/swaggard/droid-sans-v6-latin-regular.woff2 +0 -0
  15. data/app/assets/images/swaggard/logo_small.png +0 -0
  16. data/app/assets/images/swaggard/pet_store_api.png +0 -0
  17. data/app/assets/images/swaggard/throbber.gif +0 -0
  18. data/app/assets/images/swaggard/wordnik_api.png +0 -0
  19. data/app/assets/javascripts/swaggard/application.js +24 -0
  20. data/app/assets/javascripts/swaggard/lib/MD5.js +319 -0
  21. data/app/assets/javascripts/swaggard/lib/backbone-min.js +15 -0
  22. data/app/assets/javascripts/swaggard/lib/handlebars-1.0.rc.1.js +1920 -0
  23. data/app/assets/javascripts/swaggard/lib/handlebars-2.0.0.js +28 -0
  24. data/app/assets/javascripts/swaggard/lib/highlight.7.3.pack.js +1 -0
  25. data/app/assets/javascripts/swaggard/lib/jquery-1.8.0.min.js +2 -0
  26. data/app/assets/javascripts/swaggard/lib/jquery.ba-bbq.min.js +18 -0
  27. data/app/assets/javascripts/swaggard/lib/jquery.slideto.min.js +1 -0
  28. data/app/assets/javascripts/swaggard/lib/jquery.wiggle.min.js +8 -0
  29. data/app/assets/javascripts/swaggard/lib/marked.js +1272 -0
  30. data/app/assets/javascripts/swaggard/lib/shred.bundle.js +2765 -0
  31. data/app/assets/javascripts/swaggard/lib/swagger-client.js +3294 -0
  32. data/app/assets/javascripts/swaggard/lib/swagger.js +794 -0
  33. data/app/assets/javascripts/swaggard/lib/underscore-min.js +32 -0
  34. data/app/assets/javascripts/swaggard/swagger-ui.js +2240 -0
  35. data/app/assets/javascripts/swaggard/swagger-ui_org.js +2005 -0
  36. data/app/assets/stylesheets/swaggard/application.css +16 -0
  37. data/app/assets/stylesheets/swaggard/reset.css +125 -0
  38. data/app/assets/stylesheets/swaggard/screen.css.scss +1256 -0
  39. data/app/assets/stylesheets/swaggard/typography.css.scss +26 -0
  40. data/app/controllers/swaggard/application_controller.rb +4 -0
  41. data/app/controllers/swaggard/swagger_controller.rb +21 -0
  42. data/app/views/swaggard/swagger/index.html.erb +74 -0
  43. data/config/routes.rb +3 -0
  44. data/lib/swaggard.rb +92 -0
  45. data/lib/swaggard/api_definition.rb +52 -0
  46. data/lib/swaggard/configuration.rb +82 -0
  47. data/lib/swaggard/engine.rb +18 -0
  48. data/lib/swaggard/parsers/controllers.rb +30 -0
  49. data/lib/swaggard/parsers/models.rb +29 -0
  50. data/lib/swaggard/parsers/routes.rb +54 -0
  51. data/lib/swaggard/swagger/definition.rb +24 -0
  52. data/lib/swaggard/swagger/operation.rb +98 -0
  53. data/lib/swaggard/swagger/parameters/base.rb +21 -0
  54. data/lib/swaggard/swagger/parameters/body.rb +67 -0
  55. data/lib/swaggard/swagger/parameters/form.rb +32 -0
  56. data/lib/swaggard/swagger/parameters/list.rb +46 -0
  57. data/lib/swaggard/swagger/parameters/path.rb +21 -0
  58. data/lib/swaggard/swagger/parameters/query.rb +32 -0
  59. data/lib/swaggard/swagger/path.rb +24 -0
  60. data/lib/swaggard/swagger/property.rb +23 -0
  61. data/lib/swaggard/swagger/response.rb +45 -0
  62. data/lib/swaggard/swagger/tag.rb +28 -0
  63. data/lib/swaggard/swagger/type.rb +72 -0
  64. data/lib/swaggard/version.rb +5 -0
  65. data/spec/fixtures/api.json +1 -0
  66. data/spec/fixtures/dummy/app/controllers/application_controller.rb +2 -0
  67. data/spec/fixtures/dummy/app/controllers/pets_controller.rb +15 -0
  68. data/spec/fixtures/dummy/config/application.rb +15 -0
  69. data/spec/fixtures/dummy/config/environments/development.rb +5 -0
  70. data/spec/fixtures/dummy/config/routes.rb +5 -0
  71. data/spec/fixtures/dummy/log/development.log +0 -0
  72. data/spec/integration/swaggard_spec.rb +19 -0
  73. data/spec/spec_helper.rb +27 -0
  74. metadata +210 -0
@@ -0,0 +1,54 @@
1
+ module Swaggard
2
+ module Parsers
3
+ class Routes
4
+
5
+ def run(routes)
6
+ return {} unless routes
7
+
8
+ parsed_routes = {}
9
+
10
+ routes.each do |route|
11
+ controller = route_controller(route)
12
+ action = route_action(route)
13
+
14
+ parsed_routes[controller] ||= {}
15
+ parsed_routes[controller][action] = {
16
+ verb: route_verb(route),
17
+ path: route_path(route),
18
+ path_params: route_path_params(route)
19
+ }
20
+ end
21
+
22
+ parsed_routes
23
+ end
24
+
25
+ private
26
+
27
+ def route_controller(route)
28
+ route.requirements[:controller]
29
+ end
30
+
31
+ def route_action(route)
32
+ route.requirements[:action]
33
+ end
34
+
35
+ def route_verb(route)
36
+ route.verb.source.gsub(/[$^]/, '')
37
+ end
38
+
39
+ def route_path(route)
40
+ path = route.path.spec.to_s
41
+
42
+ path.gsub!('(.:format)', '')
43
+ route.required_parts.each { |part| path.gsub!(":#{part}", "{#{part}}") }
44
+
45
+ path
46
+ end
47
+
48
+ def route_path_params(route)
49
+ route.required_parts
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,24 @@
1
+ module Swaggard
2
+ module Swagger
3
+ class Definition
4
+
5
+ attr_reader :id
6
+
7
+ def initialize(id)
8
+ @id = id
9
+ @properties = []
10
+ end
11
+
12
+ def add_property(property)
13
+ @properties << property
14
+ end
15
+
16
+ def to_doc
17
+ {
18
+ 'properties' => Hash[@properties.map { |property| [property.id, property.to_doc] }]
19
+ }
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,98 @@
1
+ require_relative 'parameters/body'
2
+ require_relative 'parameters/form'
3
+ require_relative 'parameters/list'
4
+ require_relative 'parameters/path'
5
+ require_relative 'parameters/query'
6
+
7
+ require_relative 'response'
8
+
9
+ module Swaggard
10
+ module Swagger
11
+ class Operation
12
+
13
+ attr_reader :nickname
14
+ attr_accessor :path, :parameters, :description, :http_method, :summary, :notes,
15
+ :error_responses, :tag
16
+
17
+ def initialize(yard_object, tag, routes)
18
+ @name = yard_object.name
19
+ @tag = tag
20
+ @summary = yard_object.docstring.lines.first || ''
21
+ @parameters = []
22
+ @responses = []
23
+ @description = (yard_object.docstring.lines[1..-1] || []).join("\n")
24
+ @formats = Swaggard.configuration.api_formats
25
+
26
+ yard_object.tags.each do |yard_tag|
27
+ value = yard_tag.text
28
+
29
+ case yard_tag.tag_name
30
+ when 'query_parameter'
31
+ @parameters << Parameters::Query.new(value)
32
+ when 'form_parameter'
33
+ @parameters << Parameters::Form.new(value)
34
+ when 'body_parameter'
35
+ body_parameter.add_property(value)
36
+ when 'parameter_list'
37
+ @parameters << Parameters::List.new(value)
38
+ when 'response_class'
39
+ @responses << Response.new(200, value)
40
+ end
41
+ end
42
+
43
+ build_path_parameters(routes)
44
+
45
+ @parameters.sort_by { |parameter| parameter.name }
46
+ end
47
+
48
+ def valid?
49
+ @path.present?
50
+ end
51
+
52
+ def to_doc
53
+ produces = @formats.map { |format| "application/#{format}" }
54
+ consumes = @formats.map { |format| "application/#{format}" }
55
+
56
+ {
57
+ 'tags' => [@tag.name],
58
+ 'summary' => @summary,
59
+ 'description' => @description,
60
+ 'operationId' => @name,
61
+ 'consumes' => consumes,
62
+ 'produces' => produces,
63
+ 'parameters' => @parameters.map(&:to_doc),
64
+ 'responses' => Hash[@responses.map { |response| [response.status_code, response.to_doc] }]
65
+ }
66
+ end
67
+
68
+ def definitions
69
+ @body_parameter ? [@body_parameter.definition] : []
70
+ end
71
+
72
+ private
73
+
74
+ def body_parameter
75
+ return @body_parameter if @body_parameter
76
+
77
+ @body_parameter = Parameters::Body.new("#{@tag.controller_class.to_s}.#{@name}")
78
+ @parameters << @body_parameter
79
+
80
+ @body_parameter
81
+ end
82
+
83
+ def build_path_parameters(routes)
84
+ return unless @tag.controller_class
85
+
86
+ route = (routes[@tag.controller_class.controller_path] || {})[@name.to_s]
87
+
88
+ return unless route
89
+
90
+ @http_method = route[:verb]
91
+ @path = route[:path]
92
+
93
+ route[:path_params].each { |path_param| @parameters << Parameters::Path.new(path_param) }
94
+ end
95
+
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,21 @@
1
+ module Swaggard
2
+ module Swagger
3
+ module Parameters
4
+ class Base
5
+
6
+ attr_reader :name
7
+
8
+ def to_doc
9
+ {
10
+ 'in' => @in,
11
+ 'name' => @name,
12
+ 'description' => @description,
13
+ 'required' => @is_required,
14
+ 'type' => @data_type
15
+ }
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,67 @@
1
+ require_relative 'base'
2
+ require_relative '../type'
3
+
4
+ module Swaggard
5
+ module Swagger
6
+ module Parameters
7
+ class Body < Base
8
+
9
+ attr_reader :definition
10
+
11
+ def initialize(operation_name)
12
+ @in = 'body'
13
+ @name = 'body'
14
+ @description = ''
15
+ @definition = Definition.new("#{operation_name}_body")
16
+ end
17
+
18
+ def add_property(string)
19
+ property = Property.new(string)
20
+ @definition.add_property(property)
21
+ end
22
+
23
+ def to_doc
24
+ doc = super
25
+
26
+ doc.delete('type')
27
+
28
+ doc['required'] = false
29
+ doc['schema'] = { '$ref' => "#/definitions/#{@definition.id}" }
30
+
31
+ doc
32
+ end
33
+
34
+ private
35
+
36
+
37
+ class Property
38
+
39
+ attr_reader :id
40
+
41
+ def initialize(string)
42
+ parse(string)
43
+ end
44
+
45
+ def to_doc
46
+ result = @type.to_doc
47
+ result['description'] = @description if @description
48
+ result
49
+ end
50
+
51
+ # Example: [Array] status Filter by status. (e.g. status[]=1&status[]=2&status[]=3)
52
+ # Example: [Array] status(required) Filter by status. (e.g. status[]=1&status[]=2&status[]=3)
53
+ # Example: [Integer] media[media_type_id] ID of the desired media type.
54
+ def parse(string)
55
+ data_type, name, required, description = string.match(/\A\[(\w*)\]\s*([\w\[\]]*)(\(required\))?\s*(.*)\Z/).captures
56
+
57
+ @id = name
58
+ @description = description
59
+ @type = Type.new([data_type.downcase])
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,32 @@
1
+ require_relative 'base'
2
+
3
+ module Swaggard
4
+ module Swagger
5
+ module Parameters
6
+ class Form < Base
7
+
8
+ def initialize(string)
9
+ @in = 'formData'
10
+ parse(string)
11
+ end
12
+
13
+ private
14
+
15
+ # Example: [Array] status Filter by status. (e.g. status[]=1&status[]=2&status[]=3)
16
+ # Example: [Array] status(required) Filter by status. (e.g. status[]=1&status[]=2&status[]=3)
17
+ # Example: [Integer] media[media_type_id] ID of the desired media type.
18
+ def parse(string)
19
+ data_type, name, required, description = string.match(/\A\[(\w*)\]\s*([\w\[\]]*)(\(required\))?\s*(.*)\Z/).captures
20
+ allow_multiple = name.gsub!('[]', '')
21
+
22
+ @name = name
23
+ @description = description
24
+ @data_type = data_type.downcase
25
+ @is_required = required.present?
26
+ @allow_multiple = allow_multiple.present?
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,46 @@
1
+ require_relative 'base'
2
+
3
+ module Swaggard
4
+ module Swagger
5
+ module Parameters
6
+ class List < Base
7
+
8
+ def initialize(string)
9
+ @in = 'query'
10
+ parse(string)
11
+ end
12
+
13
+ def to_doc
14
+ doc = super
15
+
16
+ doc.merge(
17
+ {
18
+ 'type' => 'array',
19
+ 'items' => { 'type' => @data_type },
20
+ 'enum' => @list_values
21
+ }
22
+ )
23
+ end
24
+
25
+ private
26
+
27
+ # Example: [String] sort_order Orders ownerships by fields. (e.g. sort_order=created_at)
28
+ # [List] id
29
+ # [List] begin_at
30
+ # [List] end_at
31
+ # [List] created_at
32
+ def parse(string)
33
+ data_type, name, required, description, set_string = string.match(/\A\[(\w*)\]\s*(\w*)(\(required\))?\s*(.*)\n([.\s\S]*)\Z/).captures
34
+
35
+ @list_values = set_string.split('[List]').map(&:strip).reject { |string| string.empty? }
36
+
37
+ @name = name
38
+ @description = description
39
+ @data_type = data_type.downcase
40
+ @is_required = required.present?
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,21 @@
1
+ require_relative 'base'
2
+
3
+ module Swaggard
4
+ module Swagger
5
+ module Parameters
6
+ class Path < Base
7
+
8
+ attr_reader :name
9
+
10
+ def initialize(param_name)
11
+ @in = 'path'
12
+ @name = param_name.to_s
13
+ @data_type = 'string'
14
+ @is_required = true
15
+ @description = "Scope response to #{@name}"
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,32 @@
1
+ require_relative 'base'
2
+
3
+ module Swaggard
4
+ module Swagger
5
+ module Parameters
6
+ class Query < Base
7
+
8
+ def initialize(string)
9
+ @in = 'query'
10
+ parse(string)
11
+ end
12
+
13
+ private
14
+
15
+ # Example: [Array] status Filter by status. (e.g. status[]=1&status[]=2&status[]=3)
16
+ # Example: [Array] status(required) Filter by status. (e.g. status[]=1&status[]=2&status[]=3)
17
+ # Example: [Integer] media[media_type_id] ID of the desired media type.
18
+ def parse(string)
19
+ data_type, name, required, description = string.match(/\A\[(\w*)\]\s*([\w\[\]]*)(\(required\))?\s*(.*)\Z/).captures
20
+ allow_multiple = name.gsub!('[]', '')
21
+
22
+ @name = name
23
+ @description = description
24
+ @data_type = data_type.downcase
25
+ @is_required = required.present?
26
+ @allow_multiple = allow_multiple.present?
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,24 @@
1
+ require_relative 'operation'
2
+
3
+ module Swaggard
4
+ module Swagger
5
+ class Path
6
+
7
+ attr_reader :path
8
+
9
+ def initialize(path)
10
+ @path = path
11
+ @operations = {}
12
+ end
13
+
14
+ def add_operation(operation)
15
+ @operations[operation.http_method.downcase] = operation
16
+ end
17
+
18
+ def to_doc
19
+ Hash[@operations.map { |http_method, operation| [http_method, operation.to_doc] }]
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ require_relative 'type'
2
+
3
+ module Swaggard
4
+ module Swagger
5
+ class Property
6
+
7
+ attr_reader :id, :type, :description
8
+
9
+ def initialize(yard_object)
10
+ @id = yard_object.name
11
+ @type = Type.new(yard_object.types)
12
+ @description = yard_object.text
13
+ end
14
+
15
+ def to_doc
16
+ result = @type.to_doc
17
+ result['description'] = @description if @description
18
+ result
19
+ end
20
+
21
+ end
22
+ end
23
+ end