dry_crud_jsonapi_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.
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: []