Skip to content

Instantly share code, notes, and snippets.

@lighty
Last active March 6, 2020 05:35
Show Gist options
  • Save lighty/e0800fbe5dcfb16ccc2d3c721e5e188c to your computer and use it in GitHub Desktop.
Save lighty/e0800fbe5dcfb16ccc2d3c721e5e188c to your computer and use it in GitHub Desktop.
openapi3形式で書かれた、肥大化したスキーマ定義ファイルを分割する
# '#/components/schemas/BadRequest'
# → components/schemas/BadRequest.yml
# '#/components/responses/unauthorized'
# → components/responses.yml#/unauthorized
require 'yaml'
require 'fileutils'
require 'pry'
class RelativeDocumentReferecer
def self.execute(root, depth)
new(root, depth).execute
end
def initialize(root, depth)
@root = root
@depth = depth
end
def execute
lookup(root)
root
end
# hashで、keyが$refならconvert
# hashかarrayならlookup
# そうでないならなにもしない
def lookup(object)
if object.is_a? Array
object.each { |value| lookup(value) if value.is_a?(Hash) || value.is_a?(Array) }
else
object.each do |key, value|
set_converted_value(object, key, value) if key === "$ref"
lookup(value) if value.is_a?(Hash) || value.is_a?(Array)
end
end
end
def set_converted_value(object, key, value)
object[key] = convert(value)
end
def convert(ref)
# componentから取得することしか考えない
if ref.split('/')[2] === 'schemas'
"../" * depth + "#{ref.split('/')[1..3].join('/')}.yml"
else
"../" * depth + "#{ref.split('/')[1..2].join('/')}.yml#/#{ref.split('/')[3]}"
end
end
private
attr :root, :depth
end
class PathsObject
attr_accessor :path, :path_item_objects
def initialize(path, path_item_objects)
@path = path
@path_item_objects = path_item_objects
end
def to_file
make_directory
convert_ref
YAML.dump(path_item_objects, File.open( File.join(directory, file_name) , 'w') )
end
def make_directory
FileUtils.mkdir_p( directory )
rescue => e
puts "path: #{@path}"
throw e
end
def interlevel_directory
@path.split('/').length > 2 ? @path.split('/')[1..-2].map {|dir| dir.gsub(/[{}]/,"")} : ''
end
def directory
File.join( 'paths' , interlevel_directory)
end
def file_name
"#{@path.split('/').pop.gsub(/[{}]/,"")}.yml"
end
def ref
File.join(directory, file_name)
end
def convert_ref
RelativeDocumentReferecer.execute(path_item_objects, 1 + interlevel_directory.size)
end
end
class ComponentsObjectFieldObject
attr_accessor :field_name, :field_object
def initialize(field_name, field_object)
@field_name = field_name
@field_object = field_object
end
def to_file
convert_ref
YAML.dump(field_object, File.open( File.join(directory, file_name) , 'w') )
end
def directory
'components'
end
def file_name
"#{field_name}.yml"
end
def ref
File.join(directory, file_name)
end
def convert_ref
RelativeDocumentReferecer.execute(field_object, 1)
end
end
class SchemaObject
attr_accessor :schema_name, :schema_object
def initialize(schema_name, schema_object)
@schema_name = schema_name
@schema_object = schema_object
end
def to_file
convert_ref
YAML.dump(schema_object, File.open( File.join(directory, file_name) , 'w') )
end
def directory
'components/schemas'
end
def file_name
"#{schema_name}.yml"
end
def ref
File.join(directory, file_name)
end
def convert_ref
RelativeDocumentReferecer.execute(schema_object, 2)
end
end
open_api_object = YAML.load_file 'swagger_original.yml'
open_api_object.keys.each do |open_api_object_field|
if open_api_object_field === "paths"
FileUtils.mkdir_p('paths')
paths_objects = open_api_object[open_api_object_field]
paths_objects.keys.each do |path|
path_object = PathsObject.new(path, paths_objects[path]) # 一つのpathオブジェクト。postなどがキー
path_object.to_file
open_api_object[open_api_object_field][path] = { "$ref" => path_object.ref }
end
end
if open_api_object_field === "components"
FileUtils.mkdir_p('components')
components_objects = open_api_object[open_api_object_field]
components_objects.keys.each do |components_object_field|
if components_object_field === 'schemas'
FileUtils.mkdir_p('components/schemas')
schmas = components_objects[components_object_field]
schmas.keys.each do |schema_name|
schema_object = SchemaObject.new(schema_name, schmas[schema_name])
schema_object.to_file
open_api_object[open_api_object_field][components_object_field][schema_name] = { "$ref" => schema_object.ref }
end
else
field_object = ComponentsObjectFieldObject.new(components_object_field, components_objects[components_object_field])
field_object.to_file
open_api_object[open_api_object_field][components_object_field] = { "$ref" => field_object.ref }
end
end
end
end
YAML.dump(open_api_object, File.open( 'swagger_root.yml', 'w'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment