This commit is contained in:
YingRui Lu 2019-04-18 10:54:27 +08:00
commit c2666cec53
12 changed files with 323 additions and 0 deletions

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
/.bundle/
/.yardoc
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
Gemfile.lock

6
Gemfile Normal file
View File

@ -0,0 +1,6 @@
# frozen_string_literal: true
source 'https://rubygems.org'
# Specify your gem's dependencies in jsonapi-swagger.gemspec
gemspec

29
README.md Normal file
View File

@ -0,0 +1,29 @@
# JSONAPI Swagger
Create a JSONAPI Swagger.
## Installation
Add this line to your application's Gemfile:
```ruby
gem 'jsonapi-swagger'
```
And then execute:
$ bundle
Or install it yourself as:
$ gem install jsonapi-swagger
## Usage
```sh
rails generate jsonapi:swagger User # UserResponse < JSONAPI::Resource
```
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/superiorlu/jsonapi-swagger.

4
Rakefile Normal file
View File

@ -0,0 +1,4 @@
# frozen_string_literal: true
require 'bundler/gem_tasks'
task default: :spec

15
bin/console Executable file
View File

@ -0,0 +1,15 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'bundler/setup'
require 'jsonapi/swagger'
# You can add fixtures and/or initialization code here to make experimenting
# with your gem easier. You can also use a different console, if you like.
# (If you use this, don't forget to add pry to your Gemfile!)
# require "pry"
# Pry.start
require 'irb'
IRB.start(__FILE__)

8
bin/setup Executable file
View File

@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
set -vx
bundle install
# Do any other automated setup that you need to do here

37
jsonapi-swagger.gemspec Normal file
View File

@ -0,0 +1,37 @@
# frozen_string_literal: true
lib = File.expand_path('lib', __dir__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'jsonapi/swagger/version'
Gem::Specification.new do |spec|
spec.name = 'jsonapi-swagger'
spec.version = Jsonapi::Swagger::VERSION
spec.authors = ['YingRui Lu']
spec.email = ['yingruilu518@gmail.com']
spec.summary = 'JSON API Swagger Doc Generator'
spec.homepage = 'https://github.com/superiorlu/jsonapi-swagger'
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
# to allow pushing to a single host or delete this section to allow pushing to any host.
if spec.respond_to?(:metadata)
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
else
raise 'RubyGems 2.0 or newer is required to protect against ' \
'public gem pushes.'
end
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
spec.files = Dir['lib/**/*', 'LICENSE.md', 'README.md']
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.require_paths = ['lib']
spec.licenses = ['MIT']
spec.add_development_dependency 'bundler', '~> 2.0'
spec.add_development_dependency 'rake', '~> 10.0'
spec.add_development_dependency 'rubocop', '~> 0.67'
spec.add_dependency 'rswag', '~>2.0'
end

View File

View File

@ -0,0 +1,48 @@
# frozen_string_literal: true
module Jsonapi
class SwaggerGenerator < ::Rails::Generators::NamedBase
source_root File.expand_path('templates', __dir__)
def copy_serializable_file
template 'swagger.rb.erb',
File.join('spec/requests', class_path,
"#{spec_file_name}.rb")
end
private
def spec_file_name
"#{file_name}_spec.rb"
end
def serializable_class_name
(class_path + [serializable_file_name]).map!(&:camelize).join('::')
end
def model_klass
# TODO(beauby): Ensure the model class exists.
class_name.safe_constantize
end
def type
model_klass.model_name.plural
end
def attr_names
attrs = model_klass.new.attribute_names - ['id']
fk_attrs = model_klass.reflect_on_all_associations(:belongs_to)
.map(&:foreign_key)
attrs - fk_attrs
end
def has_one_rel_names
model_klass.reflect_on_all_associations(:has_one).map(&:name) +
model_klass.reflect_on_all_associations(:belongs_to).map(&:name)
end
def has_many_rel_names
model_klass.reflect_on_all_associations(:has_many).map(&:name)
end
end
end

View File

@ -0,0 +1,150 @@
require 'swagger_helper'
RSpec.describe '<%= resouces_name %>', type: :request do
<% if resource_klass.immutable -%>
path '/<%= route_resouces %>' do
get '<%= route_resouces %>' do
tags '<%= route_resouces %>'
produces 'application/vnd.api+json'
parameter name: :'page[number]', in: :query, type: :string, description: '页码', required: false
parameter name: :include, in: :query, type: :string, description: '包含关联数据', required: false
<% relationships.keys.each do |relation| -%>
parameter name: :'fields[<%= relation %>]', in: :query, type: :string, description: '包含字段', required: false
<% end -%>
response '200', '获取列表' do
schema type: :object,
properties: {
data: {
type: :array,
items: {
type: :object,
properties: {
id: { type: :integer, description: 'ID'},
links: {
type: :object,
properties: {
self: { type: :string, description: '详情链接'},
},
description: '详情链接'
},
attributes: {
type: :object,
properties: {
<% attributes.keys.each do |attr| -%>
<%= attr %>: { type: :<%= columns_with_comment[attr][:type] %>, description: '<%= columns_with_comment[attr][:comment] %>'},
<% end -%>
},
description: '属性'
},
relationships: {
type: :object,
properties: {
<% relationships.each do |relation_name, relation| -%>
<% relation_name_camelize = relation_name.to_s.camelize -%>
<%= relation_name %>: {
type: :object,
properties: {
links: {
type: :object,
properties: {
self: { type: :string, description: '关联<%= relation_name_camelize %>列表链接' },
related: { type: :string, description: '相关<%= relation_name_camelize %>链接' },
},
description: '相关的<%= relation_name_camelize %>链接'
},
},
description: '相关<%= relation_name_camelize %>'
},
<% end -%>
},
description: '关联数据'
}
},
},
description: '数据'
},
meta: {
type: :object,
properties: {
record_count: { type: :integer, description: '总记录数'},
page_count: { type: :integer, description: '页数'},
},
description: '分页记录数'
},
links: { type: :array, items: { type: :string }, description: '分页链接' },
},
required: [:data]
run_test!
end
end
end
path '/<%= route_resouces %>/{id}' do
get '<%= route_resouces %>详情' do
tags '<%= route_resouces %>'
produces 'application/vnd.api+json'
parameter name: :id, in: :path, type: :integer, description: 'ID', required: true
response '200', '获取详情' do
schema type: :object,
properties: {
data: {
type: :array,
items: {
type: :object,
properties: {
id: { type: :integer, description: 'ID'},
links: {
type: :object,
properties: {
self: { type: :string, description: '详情链接'},
},
description: '详情链接'
},
attributes: {
type: :object,
properties: {
<% attributes.keys.each do |attr| -%>
<%= attr %>: { type: :<%= columns_with_comment[attr][:type] %>, description: '<%= columns_with_comment[attr][:comment] %>'},
<% end -%>
},
description: '属性'
},
relationships: {
type: :object,
properties: {
<% relationships.each do |relation_name, relation| -%>
<% relation_name_camelize = relation_name.to_s.camelize -%>
<%= relation_name %>: {
type: :object,
properties: {
links: {
type: :object,
properties: {
self: { type: :string, description: '关联<%= relation_name_camelize %>列表链接' },
related: { type: :string, description: '相关<%= relation_name_camelize %>链接' },
},
description: '相关的<%= relation_name_camelize %>链接'
},
},
description: '相关<%= relation_name_camelize %>'
},
<% end -%>
},
description: '关联数据'
}
},
},
description: '数据'
},
},
required: [:data]
run_test!
end
end
end
<% else -%>
<% end -%>
end

10
lib/jsonapi/swagger.rb Normal file
View File

@ -0,0 +1,10 @@
# frozen_string_literal: true
require 'jsonapi/swagger/version'
module Jsonapi
module Swagger
class Error < StandardError; end
# Your code goes here...
end
end

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
module Jsonapi
module Swagger
VERSION = '0.1.0'
end
end