eazypi 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +80 -2
- data/lib/eazypi/api_controller.rb +1 -5
- data/lib/eazypi/components.rb +2 -1
- data/lib/eazypi/schema/array.rb +3 -1
- data/lib/eazypi/schema/object.rb +1 -0
- data/lib/eazypi/schema.rb +11 -3
- data/lib/eazypi/serializer.rb +45 -3
- data/lib/eazypi/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 38e9def08b7d5d8f9a3221b7fa25472cca0833efe5ae0cda8ae96ae0332009e8
|
4
|
+
data.tar.gz: df904e67baef641dbc1cc88f3f11cbf9f7474c2c291059fdfcaaa73feb3f7d14
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b6de60965569128c00d205656afd44b45caf9556e1cc0314ac86524d91f7173dfacb08462eb908d77a57a0fa16b474ecd04d2033afe59264ae3583b29feaa95
|
7
|
+
data.tar.gz: d0627af90001cd495935603a04a0f249f7bc98842cdd395139f1ae0f898071bd1104d74157d227b654bb869b7d5e1dd39487160932c58f652b862a9f98bbdcbe
|
data/README.md
CHANGED
@@ -46,17 +46,95 @@ class Api::V1::Example
|
|
46
46
|
end
|
47
47
|
~~~
|
48
48
|
|
49
|
+
## Define API Objects
|
50
|
+
|
51
|
+
Define API objects, they can be used with parameter objects and/or content objects in a controller
|
52
|
+
|
53
|
+
~~~
|
54
|
+
class Api::V1::Example
|
55
|
+
include Eazypi::Serializer
|
56
|
+
|
57
|
+
attribute :id, type: String, required: true
|
58
|
+
attribute :name, type: String, required: true
|
59
|
+
end
|
60
|
+
~~~
|
61
|
+
|
62
|
+
More advanced attribute types are also possible
|
63
|
+
|
64
|
+
~~~
|
65
|
+
class Api::V1::Child
|
66
|
+
include Eazypi::Serializer
|
67
|
+
|
68
|
+
attribute :id, type: String, required: true
|
69
|
+
attribute :name, type: String, required: true
|
70
|
+
|
71
|
+
attribute :alternative_names, type: [String], required: false
|
72
|
+
end
|
73
|
+
|
74
|
+
class Api::V1::ExampleWithChildren
|
75
|
+
include Eazypi::Serializer
|
76
|
+
|
77
|
+
attribute :id, type: String, required: true
|
78
|
+
attribute :name, type: String, required: true
|
79
|
+
|
80
|
+
attribute :children, type: [Child], required: false
|
81
|
+
end
|
82
|
+
~~~
|
83
|
+
|
49
84
|
### Create a controller Class
|
50
85
|
|
51
86
|
Create a normal rails controller and use the DSL to define operations.
|
52
87
|
|
53
88
|
~~~
|
54
89
|
class Api::V1::ExampleController
|
90
|
+
include include Eazypi::ApiController
|
91
|
+
|
55
92
|
operation :get, '/examples' do
|
56
|
-
|
93
|
+
parameter :filter do # By default a query parameter if it doesn't match a path parameter
|
94
|
+
description "Filter examples
|
95
|
+
|
96
|
+
schema FilterExample
|
97
|
+
end
|
98
|
+
|
99
|
+
response 200 do
|
100
|
+
description "Example"
|
101
|
+
|
102
|
+
content [API::V1::Example] # Example is defined as API Object (see above for example)
|
103
|
+
end
|
57
104
|
|
58
105
|
render do
|
59
|
-
|
106
|
+
examples = ... # Examples is array of class Example NOT API::V1::Example
|
107
|
+
respond_with examples
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
operation :get, '/example/:id' do
|
112
|
+
parameter :id do # Example of path parameter
|
113
|
+
description "Id of the pet you want to find"
|
114
|
+
|
115
|
+
schema String # Only primitive types (String, Integer, Float) are allowed in path parameters
|
116
|
+
end
|
117
|
+
|
118
|
+
response 200 do
|
119
|
+
description "Example"
|
120
|
+
|
121
|
+
content API::V1::Example # Example is defined as API Object (see above for example)
|
122
|
+
end
|
123
|
+
|
124
|
+
response 404 do
|
125
|
+
description "Not found"
|
126
|
+
|
127
|
+
content API::V1::Error
|
128
|
+
end
|
129
|
+
|
130
|
+
render do
|
131
|
+
example = Example.find_by(params[:id]) # Note Example here is ActiveRecord Object, not the API view of it
|
132
|
+
|
133
|
+
if example
|
134
|
+
respond_with example # Will serialize example object
|
135
|
+
else
|
136
|
+
respond_with Error.new(message: "Not found"), status: :not_found # Will automatically serialize Error object
|
137
|
+
end
|
60
138
|
end
|
61
139
|
end
|
62
140
|
end
|
@@ -62,11 +62,7 @@ module Eazypi
|
|
62
62
|
|
63
63
|
response_object_type = response_type.object_type_for_content_type
|
64
64
|
|
65
|
-
|
66
|
-
render json: nil, status: status
|
67
|
-
else
|
68
|
-
render json: response_type.object_type_for_content_type.new(object).to_json, status: status
|
69
|
-
end
|
65
|
+
render json: Serializer.serialize_object(response_object_type, object), status: status
|
70
66
|
end
|
71
67
|
end
|
72
68
|
end
|
data/lib/eazypi/components.rb
CHANGED
@@ -8,7 +8,8 @@ module Eazypi
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def add_schema(name, schema)
|
11
|
-
|
11
|
+
# Make sure it never gets a changed copy + never gets overwritten
|
12
|
+
@schemas[name] = schema.dup unless @schemas.key?(name)
|
12
13
|
|
13
14
|
"#/components/schemas/#{name}"
|
14
15
|
end
|
data/lib/eazypi/schema/array.rb
CHANGED
@@ -10,8 +10,10 @@ module Eazypi
|
|
10
10
|
@item_schema = item_schema
|
11
11
|
end
|
12
12
|
|
13
|
-
def collect_components(schemas: nil, **
|
13
|
+
def collect_components(schemas: nil, **kwargs)
|
14
14
|
schemas&.call(@item_schema)
|
15
|
+
|
16
|
+
@item_schema.collect_components(schemas: schemas, **kwargs)
|
15
17
|
end
|
16
18
|
|
17
19
|
def to_openapi_spec
|
data/lib/eazypi/schema/object.rb
CHANGED
data/lib/eazypi/schema.rb
CHANGED
@@ -3,21 +3,29 @@
|
|
3
3
|
module Eazypi
|
4
4
|
# JSON schema
|
5
5
|
module Schema
|
6
|
-
def self.from_object(object) # rubocop:todo Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
|
6
|
+
def self.from_object(object, parent = nil) # rubocop:todo Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
|
7
7
|
if object == :boolean
|
8
8
|
Schema::Primitive.new(type: "boolean")
|
9
9
|
elsif object.is_a?(::Array)
|
10
10
|
raise "Array needs to have one element" if object.length != 1
|
11
11
|
|
12
|
-
Schema::Array.new(Schema.from_object(object[0]))
|
12
|
+
Schema::Array.new(Schema.from_object(object[0], parent))
|
13
13
|
elsif object == String
|
14
14
|
Schema::Primitive.new(type: "string")
|
15
|
+
elsif object == Date
|
16
|
+
Schema::Primitive.new(type: "string", format: "date")
|
17
|
+
elsif object == Time
|
18
|
+
Schema::Primitive.new(type: "string", format: "date-time")
|
15
19
|
elsif object == Integer
|
16
20
|
Schema::Primitive.new(type: "integer")
|
17
21
|
elsif object == Float
|
18
22
|
Schema::Primitive.new(type: "number")
|
19
23
|
elsif object.respond_to?(:to_schema)
|
20
|
-
object
|
24
|
+
if object == parent
|
25
|
+
object.to_schema_reference
|
26
|
+
else
|
27
|
+
object.to_schema
|
28
|
+
end
|
21
29
|
else
|
22
30
|
raise "Can not convert #{object} to a schema"
|
23
31
|
end
|
data/lib/eazypi/serializer.rb
CHANGED
@@ -18,6 +18,22 @@ module Eazypi
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def serialize(object)
|
21
|
+
the_value = value(object)
|
22
|
+
|
23
|
+
Serializer.serialize_object(type, the_value)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def serialize_array(the_value)
|
29
|
+
return the_value if self.class.primitive_type?(type[0])
|
30
|
+
|
31
|
+
the_value.map do |element_value|
|
32
|
+
type[0].new(element_value).to_json
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def value(object)
|
21
37
|
if @method
|
22
38
|
@method.call(object)
|
23
39
|
elsif @method_name
|
@@ -33,12 +49,14 @@ module Eazypi
|
|
33
49
|
end
|
34
50
|
|
35
51
|
def to_json(*_args)
|
52
|
+
return nil if @object.nil?
|
53
|
+
|
36
54
|
self.class.attributes.to_h do |attribute|
|
37
55
|
[attribute.name, attribute.serialize(@object)]
|
38
56
|
end
|
39
57
|
end
|
40
58
|
|
41
|
-
included do
|
59
|
+
included do # rubocop:disable Metrics/BlockLength
|
42
60
|
@attributes = []
|
43
61
|
|
44
62
|
def self.attribute(attribute_name, type:, method: nil, method_name: nil, required: false)
|
@@ -56,14 +74,38 @@ module Eazypi
|
|
56
74
|
end
|
57
75
|
|
58
76
|
def self.to_schema
|
59
|
-
schema = Schema::Object.new(
|
77
|
+
schema = Schema::Object.new(object_name)
|
60
78
|
|
61
79
|
@attributes.each do |attribute|
|
62
|
-
schema.property attribute.name.to_s, Schema.from_object(attribute.type), required: attribute.required
|
80
|
+
schema.property attribute.name.to_s, Schema.from_object(attribute.type, self), required: attribute.required
|
63
81
|
end
|
64
82
|
|
65
83
|
schema
|
66
84
|
end
|
85
|
+
|
86
|
+
def self.to_schema_reference
|
87
|
+
Schema::Object.new(object_name).reference!("#/components/schemas/#{object_name}")
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.object_name
|
91
|
+
name.split("::").last
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.serialize_object(type_object, object) # rubocop:disable Metrics/MethodLength
|
96
|
+
if type_object.nil?
|
97
|
+
nil
|
98
|
+
elsif type_object.is_a?(Array)
|
99
|
+
object&.map do |value|
|
100
|
+
serialize_object(type_object[0], value)
|
101
|
+
end
|
102
|
+
elsif [Date, Time].include?(type_object)
|
103
|
+
object&.iso8601
|
104
|
+
elsif [String, Integer, Float].include?(type_object)
|
105
|
+
object
|
106
|
+
else
|
107
|
+
type_object.new(object).to_json
|
108
|
+
end
|
67
109
|
end
|
68
110
|
end
|
69
111
|
end
|
data/lib/eazypi/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eazypi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Samson
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-06-
|
11
|
+
date: 2024-06-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|