From c2666cec535b595565140390b4c66d4aaa85d4c9 Mon Sep 17 00:00:00 2001 From: YingRui Lu Date: Thu, 18 Apr 2019 10:54:27 +0800 Subject: [PATCH] init --- .gitignore | 9 ++ Gemfile | 6 + README.md | 29 ++++ Rakefile | 4 + bin/console | 15 ++ bin/setup | 8 + jsonapi-swagger.gemspec | 37 +++++ lib/generators/jsonapi/swagger/USAGE | 0 .../jsonapi/swagger/swagger_generator.rb | 48 ++++++ .../jsonapi/swagger/templates/swagger.rb.erb | 150 ++++++++++++++++++ lib/jsonapi/swagger.rb | 10 ++ lib/jsonapi/swagger/version.rb | 7 + 12 files changed, 323 insertions(+) create mode 100644 .gitignore create mode 100644 Gemfile create mode 100644 README.md create mode 100644 Rakefile create mode 100755 bin/console create mode 100755 bin/setup create mode 100644 jsonapi-swagger.gemspec create mode 100644 lib/generators/jsonapi/swagger/USAGE create mode 100644 lib/generators/jsonapi/swagger/swagger_generator.rb create mode 100644 lib/generators/jsonapi/swagger/templates/swagger.rb.erb create mode 100644 lib/jsonapi/swagger.rb create mode 100644 lib/jsonapi/swagger/version.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1f8fbb9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +/.bundle/ +/.yardoc +/_yardoc/ +/coverage/ +/doc/ +/pkg/ +/spec/reports/ +/tmp/ +Gemfile.lock \ No newline at end of file diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..9177aa9 --- /dev/null +++ b/Gemfile @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' + +# Specify your gem's dependencies in jsonapi-swagger.gemspec +gemspec diff --git a/README.md b/README.md new file mode 100644 index 0000000..7510acd --- /dev/null +++ b/README.md @@ -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. diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..7f6fc4a --- /dev/null +++ b/Rakefile @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +require 'bundler/gem_tasks' +task default: :spec diff --git a/bin/console b/bin/console new file mode 100755 index 0000000..6f26933 --- /dev/null +++ b/bin/console @@ -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__) diff --git a/bin/setup b/bin/setup new file mode 100755 index 0000000..dce67d8 --- /dev/null +++ b/bin/setup @@ -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 diff --git a/jsonapi-swagger.gemspec b/jsonapi-swagger.gemspec new file mode 100644 index 0000000..d9c1020 --- /dev/null +++ b/jsonapi-swagger.gemspec @@ -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 diff --git a/lib/generators/jsonapi/swagger/USAGE b/lib/generators/jsonapi/swagger/USAGE new file mode 100644 index 0000000..e69de29 diff --git a/lib/generators/jsonapi/swagger/swagger_generator.rb b/lib/generators/jsonapi/swagger/swagger_generator.rb new file mode 100644 index 0000000..5fcf2ed --- /dev/null +++ b/lib/generators/jsonapi/swagger/swagger_generator.rb @@ -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 diff --git a/lib/generators/jsonapi/swagger/templates/swagger.rb.erb b/lib/generators/jsonapi/swagger/templates/swagger.rb.erb new file mode 100644 index 0000000..221ed4f --- /dev/null +++ b/lib/generators/jsonapi/swagger/templates/swagger.rb.erb @@ -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 diff --git a/lib/jsonapi/swagger.rb b/lib/jsonapi/swagger.rb new file mode 100644 index 0000000..669ce7e --- /dev/null +++ b/lib/jsonapi/swagger.rb @@ -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 diff --git a/lib/jsonapi/swagger/version.rb b/lib/jsonapi/swagger/version.rb new file mode 100644 index 0000000..ead45fd --- /dev/null +++ b/lib/jsonapi/swagger/version.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module Jsonapi + module Swagger + VERSION = '0.1.0' + end +end