dry_crud_jsonapi_swagger 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2ca6f8559b627d78879620ecdc23cf364c2c66a9bdc250413583822a207c2bdb
4
+ data.tar.gz: acd211a583d25f1b71793298e05fde5cf4eee4fb3f09eba1c673256abed65a30
5
+ SHA512:
6
+ metadata.gz: 42337d4de64d59e9c28e6cc456e5f5dd7c7b919618de928a0a9fbc8a1fa9564b114044e55e958deae231d8258c71de26979cff06c357871a90a5f372c918bb44
7
+ data.tar.gz: 64089c5fdf47d6797861726b496811b4f7a05978ce29f33f76eb7c0af6095583da13acbfcb8a6e68fc4499f6160f92a6385a5f37cbbcd0dd3ab9b81d206e1697
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # DryCrudJsonapiSwagger
2
+ Short description and motivation.
3
+
4
+ ## Usage
5
+ How to use my plugin.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'dry_crud_jsonapi_swagger'
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install dry_crud_jsonapi_swagger
22
+ ```
23
+
24
+ ## Contributing
25
+ Contribution directions go here.
26
+
27
+ ## License
28
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require "bundler/gem_tasks"
@@ -0,0 +1,31 @@
1
+ class ApidocsController < ApplicationController
2
+ skip_before_action :authenticate, only: [:show]
3
+ skip_authorization_check
4
+
5
+ layout false
6
+
7
+ def show
8
+ respond_to do |format|
9
+ format.html
10
+ format.json { render json: generate_doc }
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def generate_doc
17
+ Swagger::Setup.new(request.url, controller_classes).run
18
+ end
19
+
20
+ def controller_classes
21
+ Rails.application.eager_load! if Rails.env.development?
22
+ json_api_controllers
23
+ end
24
+
25
+ def json_api_controllers
26
+ ListController.descendants.select { |model| model.include?(DryCrudJsonapi) }.select do |controller|
27
+ controller.model_class rescue false
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,37 @@
1
+ module Swagger
2
+ class ControllerSetup
3
+ include Rails.application.routes.url_helpers
4
+ include Swagger::Helper
5
+ attr_reader :controller_class
6
+
7
+ def initialize(controller_class)
8
+ @controller_class = controller_class
9
+ end
10
+
11
+ def run
12
+ setup_index_path
13
+ setup_show_path
14
+ end
15
+
16
+ def setup_index_path
17
+ setup_swagger_path(index_path) do |helper|
18
+ helper.path_spec(self, helper, :index)
19
+ end
20
+ end
21
+
22
+ def setup_show_path
23
+ setup_swagger_path(show_path) do |helper|
24
+ helper.path_spec(self, helper, :show)
25
+ end
26
+ end
27
+
28
+ def show_path
29
+ polymorphic_path(model_name.singular_route_key, id: 1) rescue nil
30
+ end
31
+
32
+ def index_path
33
+ polymorphic_path(model_name.route_key) rescue nil
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,130 @@
1
+ module Swagger
2
+ module Helper
3
+
4
+ def setup_swagger_path(path, helper = self, &block)
5
+ return unless path
6
+ @path = path.gsub('1', '{id}')
7
+ controller_class.send(:swagger_path, @path) do
8
+ instance_exec(helper, &block)
9
+ end
10
+ end
11
+
12
+ def model_name
13
+ controller_class.model_class.model_name
14
+ end
15
+
16
+ def human_name
17
+ model_name.human
18
+ end
19
+
20
+ def nested_human_name
21
+ nested_model_name.human
22
+ end
23
+
24
+ def controller_route
25
+ controller_class.model_class.new(id: 1)
26
+ end
27
+
28
+ def nested_root_path
29
+ nested_model_name.route_key
30
+ end
31
+
32
+ def nested_controller_id
33
+ controller_class.model_class.model_name.route_key.singularize + '_id'
34
+ end
35
+
36
+ def nested_model_name
37
+ nested_class.model_class.model_name
38
+ end
39
+
40
+ def description(controller = controller_class)
41
+ # relationships = controller.model_class
42
+ # .reflect_on_all_associations(:belongs_to)
43
+ # .map(&:name).sort
44
+ #
45
+ # relationships += controller.model_class
46
+ # .reflect_on_all_associations(:has_many)
47
+ # .map(&:name).sort
48
+
49
+ relationships = controller.model_class
50
+ .reflect_on_all_associations
51
+ .map(&:name).sort
52
+
53
+ 'The following relationships are available: ' \
54
+ "#{relationships.join(', ')} (separate values with a comma)"
55
+ end
56
+
57
+ def path_spec(swagger_doc, helper, type) # rubocop:disable Metrics/MethodLength
58
+ summary =
59
+ case type.to_sym
60
+ when :index then "All #{human_name.pluralize}"
61
+ when :show then "Single #{human_name}"
62
+ when :nested then "All #{nested_human_name.pluralize} belonging to #{human_name}"
63
+ end
64
+
65
+ swagger_doc.operation :get do
66
+ key :summary, summary
67
+ helper.setup_tags(self)
68
+ helper.parameters(self, helper, type)
69
+ response 200 do
70
+ key :description, summary + ' Response'
71
+ helper.response_schema(self, helper, type)
72
+ end
73
+ end
74
+ end
75
+
76
+ def setup_tags(swagger_doc)
77
+ swagger_doc.key :tags, [
78
+ 'All',
79
+ Swagger::TagsSetup.path_tag(@path)
80
+ ]
81
+ end
82
+
83
+ def parameters(swagger_doc, helper, type)
84
+ case type.to_sym
85
+ when :show, :nested then parameter_id swagger_doc, helper
86
+ end
87
+
88
+ parameter_include swagger_doc, helper, type
89
+ end
90
+
91
+ def parameter_id(swagger_doc, helper)
92
+ swagger_doc.parameter do
93
+ key :name, :id
94
+ key :in, :path
95
+ key :description, "ID of #{helper.human_name} to fetch"
96
+ key :required, true
97
+ key :type, :integer
98
+ end
99
+ end
100
+
101
+ def parameter_include(swagger_doc, helper, type) # rubocop:disable Metrics/MethodLength
102
+ desc = case type.to_sym
103
+ when :index, :show then description
104
+ when :nested then description helper.nested_class
105
+ end
106
+ swagger_doc.parameter do
107
+ key :name, :include
108
+ key :in, :query
109
+ key :description, desc
110
+ key :required, false
111
+ key :type, :string
112
+ end
113
+ end
114
+
115
+ def response_schema(swagger_doc, helper, type)
116
+ ref = case type.to_sym
117
+ when :index, :show then helper.model_name
118
+ when :nested then helper.nested_model_name
119
+ end
120
+
121
+ swagger_doc.schema do
122
+ key :type, :array
123
+ items do
124
+ key :'$ref', ref
125
+ end
126
+ end
127
+ end
128
+
129
+ end
130
+ end
@@ -0,0 +1,53 @@
1
+ module Swagger
2
+ class NestedControllerSetup
3
+ include Rails.application.routes.url_helpers
4
+ include Swagger::Helper
5
+
6
+ attr_reader :controller_class, :controller_classes, :nested_class
7
+
8
+ def initialize(controller_classes, controller_class)
9
+ @controller_classes = controller_classes
10
+ @controller_class = controller_class
11
+ end
12
+
13
+ def run
14
+ setup_nestings
15
+ end
16
+
17
+ private
18
+
19
+ def setup_nestings
20
+ collect_nestings.each do |nested|
21
+ @nested_class = nested
22
+ setup_nesting
23
+ end
24
+ end
25
+
26
+ def setup_nesting
27
+ setup_swagger_path(nested_path) do |helper|
28
+ helper.path_spec(self, helper, :nested)
29
+ end
30
+ end
31
+
32
+ def nested_path
33
+ polymorphic_path([controller_route, nested_root_path]) rescue nil
34
+ end
35
+
36
+ def collect_nestings
37
+ controller_classes.collect do |controller|
38
+ controller if nested? controller
39
+ end.flatten.compact
40
+ end
41
+
42
+ def nested?(controller)
43
+ return false if controller == controller_class
44
+
45
+ nested = []
46
+ #nested << controller.optional_nesting || []
47
+ nested << controller.nesting || []
48
+
49
+ nested.flatten.include? controller_class.model_class
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,102 @@
1
+ module Swagger
2
+ class Setup
3
+ attr_reader :request_uri, :controller_classes
4
+
5
+ def initialize(request_url, controller_classes)
6
+ @request_uri = URI.parse(request_url)
7
+ @controller_classes = controller_classes
8
+ end
9
+
10
+ def run
11
+ swaggered_classes = [setup_metadata, setup_controllers, setup_models].flatten
12
+ Swagger::Blocks.build_root_json(swaggered_classes)
13
+ end
14
+
15
+ def host
16
+ "#{request_uri.host}:#{request_uri.port}"
17
+ end
18
+
19
+ def json_api_mimetype
20
+ JSONAPI::Rails::Railtie::MEDIA_TYPE
21
+ end
22
+
23
+ def setup_tags(swagger_doc)
24
+ Swagger::TagsSetup.new(swagger_doc).run
25
+ end
26
+
27
+ private
28
+
29
+ def setup_metadata # rubocop:disable Metrics/MethodLength
30
+ ApidocsController.instance_exec(self) do |helper|
31
+ include Swagger::Blocks
32
+ swagger_root do
33
+ key :swagger, '2.0'
34
+ info do
35
+ key :version, Puzzletime.version
36
+ key :title, 'Puzzletime'
37
+ contact do
38
+ key :name, 'Puzzletime Team'
39
+ end
40
+ end
41
+ helper.setup_tags(self)
42
+ key :host, helper.host
43
+ key :schemes, [helper.request_uri.scheme]
44
+ key :basePath, '/'
45
+ key :produces, [helper.json_api_mimetype]
46
+ key :consumes, [helper.json_api_mimetype]
47
+ security_definition 'BasicAuth' do
48
+ key :type, 'basic'
49
+ end
50
+ end
51
+ end
52
+ ApidocsController
53
+ end
54
+
55
+ def setup_controllers
56
+ controller_classes.each(&method(:setup_controller))
57
+ controller_classes
58
+ end
59
+
60
+ def setup_models
61
+ exposed_models.each(&method(:setup_model))
62
+ exposed_models
63
+ end
64
+
65
+ def exposed_models
66
+ root_models = controller_classes.map(&:model_class)
67
+ (root_models + root_models.map(&:reflect_on_all_associations).flatten.map(&:klass)).uniq
68
+ end
69
+
70
+ def setup_model(model_class)
71
+ model_class.instance_exec(self) do |_helper|
72
+ include Swagger::Blocks
73
+ swagger_schema model_class.name.to_sym do
74
+ model_class.columns.each do |column|
75
+ property column.name do
76
+ case column.type
77
+ when :float
78
+ key :type, 'number'
79
+ when :date
80
+ key :type, 'string'
81
+ key :format, 'date'
82
+ when :time
83
+ key :type, 'string'
84
+ key :format, 'date-time'
85
+ else
86
+ key :type, column.type
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ def setup_controller(controller_class)
95
+ controller_class.send :include, Swagger::Blocks
96
+ Swagger::ControllerSetup.new(controller_class).run
97
+ Swagger::NestedControllerSetup.new(controller_classes, controller_class).run
98
+ end
99
+
100
+ end
101
+
102
+ end
@@ -0,0 +1,46 @@
1
+ module Swagger
2
+ class TagsSetup
3
+
4
+ def initialize(swagger_doc = nil)
5
+ @swagger_doc = swagger_doc
6
+ end
7
+
8
+ def run
9
+ setup_tags
10
+ end
11
+
12
+ def self.path_tag(path)
13
+ new.get_tag_by_path(path)
14
+ end
15
+
16
+ def get_tag_by_path(path)
17
+ tags.each do |tag|
18
+ next if tag['include'].blank?
19
+
20
+ tag['include'].each do |inc|
21
+ return tag['name'] if path =~ /#{inc}/i
22
+ end
23
+
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+
30
+ def setup_tags
31
+ tags.each do |tag|
32
+ @swagger_doc.tags tag.slice('name', 'description', 'externalDocs')
33
+ end
34
+ end
35
+
36
+ def tags
37
+ @tags ||= load_tags['tags']
38
+ end
39
+
40
+ def load_tags
41
+ require 'yaml'
42
+ YAML.load_file(Rails.root.join('config', 'swagger-tags.yml')) # TODO: what is this for? fill yml with sensible values
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,10 @@
1
+ Rswag::Ui.configure do |c|
2
+
3
+ # List the Swagger endpoints that you want to be documented through the swagger-ui
4
+ # The first parameter is the path (absolute or relative to the UI host) to the corresponding
5
+ # JSON endpoint and the second is a title that will be displayed in the document selector
6
+ # NOTE: If you're using rspec-api to expose Swagger files (under swagger_root) as JSON endpoints,
7
+ # then the list below should correspond to the relative paths for those endpoints
8
+
9
+ c.swagger_endpoint '/apidocs.json', 'API Docs'
10
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ Rails.application.routes.draw do
2
+ mount Rswag::Ui::Engine => '/apidocs'
3
+ get 'apidocs', to: 'apidocs#show', constraints: { format: 'json' }
4
+ end
@@ -0,0 +1,7 @@
1
+ require "rswag/ui"
2
+ require "swagger/blocks"
3
+
4
+ module DryCrudJsonapiSwagger
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module DryCrudJsonapiSwagger
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,5 @@
1
+ require "dry_crud_jsonapi_swagger/engine"
2
+
3
+ module DryCrudJsonapiSwagger
4
+ # Your code goes here...
5
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dry_crud_jsonapi_swagger
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Illi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-01-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.17'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.17'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: dry_crud_jsonapi
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: rswag-ui
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 2.0.5
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 2.0.5
69
+ - !ruby/object:Gem::Dependency
70
+ name: swagger-blocks
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 2.0.2
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 2.0.2
83
+ description:
84
+ email:
85
+ - illi@puzzle.ch
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - README.md
91
+ - Rakefile
92
+ - app/controllers/apidocs_controller.rb
93
+ - app/domain/swagger/controller_setup.rb
94
+ - app/domain/swagger/helper.rb
95
+ - app/domain/swagger/nested_controller_setup.rb
96
+ - app/domain/swagger/setup.rb
97
+ - app/domain/swagger/tags_setup.rb
98
+ - config/initializers/rswag-ui.rb
99
+ - config/routes.rb
100
+ - lib/dry_crud_jsonapi_swagger.rb
101
+ - lib/dry_crud_jsonapi_swagger/engine.rb
102
+ - lib/dry_crud_jsonapi_swagger/version.rb
103
+ homepage: https://rubygems.org/gems/dry_crud_jsonapi_swagger
104
+ licenses:
105
+ - MIT
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.7.6
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Automatic swagger documentation for dry_crud_jsonapi
127
+ test_files: []