Skip to content

Commit

Permalink
feat(swagger-object) : Improve object creation
Browse files Browse the repository at this point in the history
Add creation of Swagger::Object by some object instance

(Related to icyleaf#18)
  • Loading branch information
MathiusD committed Dec 19, 2022
1 parent 8bc78a8 commit 2a1802d
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 1 deletion.
26 changes: 26 additions & 0 deletions spec/swagger/object_spec.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
require "../spec_helper"

struct Project
property id, name, description, vcs, open_source

def initialize(@id : Int32, @name : String, @vcs : String, @open_source : Bool, @description : String? = nil)
end
end

describe Swagger::Object do
describe "#new" do
it "should works" do
Expand Down Expand Up @@ -41,5 +48,24 @@ describe Swagger::Object do
raw.properties.should be_nil
raw.items.should eq("Comment")
end

it "should generate schema of object from object instance" do
raw = Swagger::Object.create_from_instance(
Project.new(1, "swagger", "git", true, "Swagger contains a OpenAPI / Swagger universal documentation generator and HTTP server handler.")
)
raw.name.should eq "Project"
raw.type.should eq "object"
raw.properties.should eq [
Swagger::Property.new("id", "integer", "int32", example: 1, required: true),
Swagger::Property.new("name", example: "swagger", required: true),
Swagger::Property.new("vcs", example: "git", required: true),
Swagger::Property.new("open_source", "boolean", example: true, required: true),
Swagger::Property.new(
"description",
example: "Swagger contains a OpenAPI / Swagger universal documentation generator and HTTP server handler.",
required: false
),
]
end
end
end
3 changes: 2 additions & 1 deletion src/swagger/http/handler.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ require "http/server/handler"
module Swagger::HTTP::Handler
macro included
include ::HTTP::Handler

def not_found(context)
response_with(context, {
message: "not_found"
message: "not_found",
}, status_code: 404)
end

Expand Down
27 changes: 27 additions & 0 deletions src/swagger/object.cr
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,32 @@ module Swagger
def initialize(@name : String, @type : String, @properties : Array(Property)? = nil,
@items : (self | String)? = nil)
end

def self.create_from_instance(reflecting instance : T, custom_name : String? = nil) forall T
{% begin %}
properties = [] of Property
{% for ivar in T.instance.instance_vars %}
{{ iname = ivar.name.stringify }}
swagger_data_type = Utils::SwaggerDataType.create_from_class({{ ivar.type }})
{{ irequired = !ivar.type.union? }}
value = {% if T.class? || T.struct? %} instance.{{ ivar.name }} {% else %} {{ ivar.default_value.stringify }} {% end %}
properties << Property.new(
{{ iname }},
swagger_data_type.type,
format: swagger_data_type.format,
{% if ivar.type <= String || ivar.type <= Int32 ||
ivar.type <= Int64 || ivar.type <= Float64 ||
ivar.type <= Bool %}
example: value,
{% else %}
example: value.to_s,
{% end %}
required: {{ irequired }}
)
{% end %}

self.new(custom_name ? custom_name.as(String) : instance.class.name, "object", properties)
{% end %}
end
end
end
48 changes: 48 additions & 0 deletions src/swagger/utils.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
module Utils
struct SwaggerDataType
property type : String
property format : String?

def initialize(@type : String, @format : String?)
end

def self.create_from_class(type : T.class) forall T
{% begin %}
{% if T.union? %}
return self.create_from_class({{ T.union_types.find { |var| var != Nil } }})
{% else %}
# Cf https://swagger.io/specification/#data-types
{% if T <= String || T <= Nil %}
swagger_type = "string"
swagger_format = nil
{% elsif T <= Int %}
swagger_type = "integer"
{% if T <= Int32 %}
swagger_format = "int32"
{% elsif T <= Int64 %}
swagger_format = "int64"
{% else %}
swagger_format = nil
{% end %}
{% elsif T <= Number %}
swagger_type = "number"
{% if T <= Float32 %}
swagger_format = "float"
{% elsif T <= Float64 %}
swagger_format = "double"
{% else %}
swagger_format = nil
{% end %}
{% elsif T <= Bool %}
swagger_type = "boolean"
swagger_format = nil
{% else %}
swagger_type = {{ T.stringify }}
swagger_format = nil
{% end %}
return self.new(swagger_type, swagger_format)
{% end %}
{% end %}
end
end
end

0 comments on commit 2a1802d

Please sign in to comment.