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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bfe47c3c3c7c8c3ac25c0d67311957fb2672599ea81f48e6247f82b9fae6710b
4
- data.tar.gz: 436ec6c096a12482add4ac1a0245b4c555e254fd3be329ba9549e6b1422a1154
3
+ metadata.gz: 38e9def08b7d5d8f9a3221b7fa25472cca0833efe5ae0cda8ae96ae0332009e8
4
+ data.tar.gz: df904e67baef641dbc1cc88f3f11cbf9f7474c2c291059fdfcaaa73feb3f7d14
5
5
  SHA512:
6
- metadata.gz: f849fdc4f64b2471955dcf1b8517e6bd445d2285b646384c6081b6aa9ffb87d78e9be72a093c4731436ea6fd4340561a2b1aa89886cdb3e53f0c8007bfd704d6
7
- data.tar.gz: 62e8ba592f52624d36bedba28e96f463956c6ae3cb16e1aa2d89acfc060459bc897d2034bdfa8e7423b7222104f0f4bca0acdbe4729358d821abc9d3cf5a91ce
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
- response 200, [String]
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
- render json: { examples: ['A', 'B'] }
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
- if response_object_type.nil?
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
@@ -8,7 +8,8 @@ module Eazypi
8
8
  end
9
9
 
10
10
  def add_schema(name, schema)
11
- @schemas[name] = schema.dup # Make sure it never gets a reference
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
@@ -10,8 +10,10 @@ module Eazypi
10
10
  @item_schema = item_schema
11
11
  end
12
12
 
13
- def collect_components(schemas: nil, **_kwargs)
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
@@ -15,6 +15,7 @@ module Eazypi
15
15
 
16
16
  def reference!(reference)
17
17
  @reference = reference
18
+ self
18
19
  end
19
20
 
20
21
  def property(name, schema, required: false)
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.to_schema
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
@@ -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(name.split("::").last)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Eazypi
4
- VERSION = "0.0.3"
4
+ VERSION = "0.0.5"
5
5
  end
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.3
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-06 00:00:00.000000000 Z
11
+ date: 2024-06-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack