Skip to content

Produce valid swagger json #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions lib/generators/jsonapi/swagger/swagger_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,18 @@ def swagger_info
JSON.pretty_generate(Jsonapi::Swagger.info)
end

def swagger_host
Jsonapi::Swagger.host
end

def swagger_base_path
Jsonapi::Swagger.base_path
end

def swagger_security_definitions
JSON.pretty_generate(Jsonapi::Swagger.security_definitions)
end

def swagger_file_path
Jsonapi::Swagger.file_path
end
Expand All @@ -66,11 +74,11 @@ def resouces_name
end

def route_resouces
resouces_name.tableize
resouces_name.tableize.dasherize
end

def model_class_name
(class_path + [file_name]).map!(&:camelize).join("::")
(class_path + [file_name]).map!(&:camelize).join('::')
end

def sortable_fields_desc
Expand Down Expand Up @@ -133,7 +141,7 @@ def columns_with_comment(need_encoding: true)
model_klass.columns.each do |col|
col_name = transform_method ? col.name.send(transform_method) : col.name
is_array = col.respond_to?(:array) ? col.array : false
clos[col_name.to_sym] = { type: swagger_type(col), items_type: col.type, is_array: is_array, nullable: col.null, comment: col.comment }
clos[col_name.to_sym] = { type: swagger_type(col), items_type: col.type, is_array: is_array, nullable: col.null, comment: col.comment }
clos[col_name.to_sym][:comment] = safe_encode(col.comment) if need_encoding
end
end
Expand All @@ -154,12 +162,12 @@ def relation_table_name(relation)
return relation.name if relation.respond_to?(:name)
end

def t(key, options={})
def t(key, options = {})
content = tt(key, options)
safe_encode(content)
end

def tt(key, options={})
def tt(key, options = {})
options[:scope] = :jsonapi_swagger
options[:default] = key.to_s.humanize
I18n.t(key, options)
Expand Down
149 changes: 77 additions & 72 deletions lib/generators/jsonapi/swagger/templates/swagger.json.erb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"swagger": "<%= swagger_version %>",
"info": <%= swagger_info %>,
"host": "<%= swagger_host %>",
"basePath" : "<%= swagger_base_path %>",
"securityDefinitions": <%= swagger_security_definitions %>,
<%-
def list_resource_parameters
[].tap do |parameters|
Expand All @@ -20,10 +22,14 @@
relationships.each_value do |relation|
parameters << { name: :"fields[#{relation_table_name(relation)}]", in: :query, type: :string, description: tt(:display_field), required: false }
end
duplicate = parameters.detect{ |el| parameters.count(el) > 1 }
if duplicate
parameters.delete_at(parameters.find_index(duplicate))
end
end
end

def show_resource_parameters
def detail_resource_parameters
[].tap do |parameters|
parameters << { name: :id, in: :path, type: :integer, description: 'ID', required: true }
if relationships.present?
Expand All @@ -33,37 +39,42 @@
relationships.each_value do |relation|
parameters << { name: :"fields[#{relation_table_name(relation)}]", in: :query, type: :string, description: tt(:display_field), required: false }
end
duplicate = parameters.detect{ |el| parameters.count(el) > 1 }
if duplicate
parameters.delete_at(parameters.find_index(duplicate))
end
end
end

def create_resource_parameters
parameters = {
name: :data,
in: :body,
type: :object,
properties: {
data: {
type: :object,
properties: {
type: { type: :string, default: route_resouces },
attributes: {
type: :object,
properties: properties(attrs: creatable_fields)
schema: {
properties: {
data: {
type: :object,
properties: {
type: { type: :string, default: route_resouces },
attributes: {
type: :object,
properties: properties(attrs: creatable_fields)
}
}
}
},
}
},
description: tt(:request_body)
}
parameters[:properties][:data][:properties][:relationships] ||= {}
parameters[:properties][:data][:properties][:relationships] = { type: :object, properties: create_relationships_properties }
parameters[:schema][:properties][:data][:properties][:relationships] ||= {}
parameters[:schema][:properties][:data][:properties][:relationships] = { type: :object, properties: create_relationships_properties }
parameters
end

def patch_resource_parameters
patch_parameters = create_resource_parameters.dup
patch_parameters[:properties][:data][:properties][:id] ||= {}
patch_parameters[:properties][:data][:properties][:id].merge!({ type: :integer, description: 'ID' })
patch_parameters[:schema][:properties][:data][:properties][:id] ||= {}
patch_parameters[:schema][:properties][:data][:properties][:id].merge!({ type: :integer, description: 'ID' })
parameters = [{ name: :id, in: :path, type: :integer, description: 'ID', required: true }]
parameters << patch_parameters
parameters
Expand All @@ -76,11 +87,13 @@
def properties(attrs: [])
Hash.new{|h, k| h[k] = {}} .tap do |props|
attrs.each do |attr|
columns = columns_with_comment(need_encoding: false)
props[attr][:type] = columns[attr][:type]
props[attr][:items] = { type: columns[attr][:items_type] } if columns[attr][:is_array]
props[attr][:'x-nullable'] = columns[attr][:nullable]
props[attr][:description] = columns[attr][:comment]
# We dasherize the attribute key because JSONApiResources needs attributes to be dasherized
dasherizedAttr = attr.to_s.gsub("_", "-")
columns = columns_with_comment(need_encoding: false)
props[dasherizedAttr][:type] = columns[attr][:type]
props[dasherizedAttr][:items] = { type: columns[attr][:items_type] } if columns[attr][:is_array]
props[dasherizedAttr][:'x-nullable'] = columns[attr][:nullable]
props[dasherizedAttr][:description] = columns[attr][:comment] || ''
end
end
end
Expand Down Expand Up @@ -199,7 +212,7 @@
}
end

def show_resource_responses
def detail_resource_responses
{
'200' => {
description: tt(:get_detail),
Expand All @@ -208,6 +221,8 @@
}
end

alias patch_resource_responses detail_resource_responses

def create_resource_responses
{
'201' => {
Expand Down Expand Up @@ -257,63 +272,53 @@
}
end

doc['paths']["/#{route_resouces}"] = {
get: {
summary: "#{route_resouces} #{tt(:list)}",
tags: [route_resouces],
produces: ['application/vnd.api+json'],
parameters: list_resource_parameters,
responses: list_resource_responses
}
}
current_resource = file_name.pluralize
id = ActiveRecord::Base.connection.exec_query("SELECT id FROM #{current_resource} LIMIT 1").to_a[0]["id"]

doc['paths']["/#{route_resouces}"] = {}
doc['paths']["/#{route_resouces}/{id}"] = {}

[:list, :detail, :create, :patch, :delete].each do |action|
method = action
if action == :list || action == :detail
method = :get
elsif action == :create
method = :post
end

doc['paths']["/#{route_resouces}/{id}"] = {
get: {
summary: "#{route_resouces} #{tt(:detail)}",
path_hash = Hash.new
path_hash[method] = {
summary: "#{route_resouces} #{tt(action)}",
tags: [route_resouces],
consumes: ['application/vnd.api+json'],
produces: ['application/vnd.api+json'],
parameters: show_resource_parameters,
responses: show_resource_responses
security: [{ BasicAuth: [] }],
parameters: send("#{action.to_s}_resource_parameters"),
responses: send("#{action.to_s}_resource_responses")
}
}

if mutable?
doc['paths']["/#{route_resouces}"].merge!({
post: {
summary: "#{route_resouces} #{tt(:create)}",
tags: [route_resouces],
consumes: ['application/vnd.api+json'],
produces: ['application/vnd.api+json'],
parameters: [create_resource_parameters],
responses: create_resource_responses
}
})
if action == :create
path_hash[method][:parameters] = [path_hash[method][:parameters]]
end

doc['paths']["/#{route_resouces}/{id}"].merge!({
patch: {
summary: "#{route_resouces} #{tt(:patch)}",
tags: [route_resouces],
consumes: ['application/vnd.api+json'],
produces: ['application/vnd.api+json'],
parameters: patch_resource_parameters,
responses: show_resource_responses
}
})
if action == :list || action == :create
if Rails.application.routes.recognize_path("#{route_resouces}", method: method)[:action] != 'error'
doc['paths']["/#{route_resouces}"].merge!(path_hash)
end
else
if Rails.application.routes.recognize_path("#{route_resouces}/#{id}", method: method)[:action] != 'error'
doc['paths']["/#{route_resouces}/{id}"].merge!(path_hash)
end
end
end

doc['paths']["/#{route_resouces}/{id}"].merge!({
delete: {
summary: "#{route_resouces} #{tt(:delete)}",
tags: [route_resouces],
produces: ['application/vnd.api+json'],
parameters: delete_resource_parameters,
responses: delete_resource_responses
}
})
else
doc['paths']["/#{route_resouces}"].delete(:post)
doc['paths']["/#{route_resouces}/{id}"].delete(:patch)
doc['paths']["/#{route_resouces}/{id}"].delete(:delete)
end
-%>
if doc['paths']["/#{route_resouces}"] == {}
doc['paths'].delete("/#{route_resouces}")
end

if doc['paths']["/#{route_resouces}/{id}"] == {}
doc['paths'].delete("/#{route_resouces}/{id}")
end
-%>
"paths": <%= JSON.pretty_generate(doc['paths'] ) %>
}
10 changes: 9 additions & 1 deletion lib/jsonapi/swagger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module Swagger
class Error < StandardError; end

class << self
attr_accessor :version, :info, :file_path, :base_path, :use_rswag
attr_accessor :version, :info, :file_path, :base_path, :host, :use_rswag

def config
yield self
Expand All @@ -32,6 +32,14 @@ def base_path
@base_path
end

def host
@host
end

def security_definitions
@security_definitions ||= { BasicAuth: { type: 'basic' } }
end

def use_rswag
@use_rswag ||= false
end
Expand Down
4 changes: 4 additions & 0 deletions lib/jsonapi/swagger/json.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ def parse_doc
@doc ||= JSON.parse(load) rescue Hash.new{ |h, k| h[k]= {} }
end

def host
Jsonapi::Swagger.host
end

def base_path
Jsonapi::Swagger.base_path
end
Expand Down