eazypi 0.0.2 → 0.0.4

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: 344baf3f0f1dacd826dae2caf2aeda6172c78dcd72c4b5a3a8e05f691ccf1a4e
4
- data.tar.gz: 5ac7965a5e48ad5962dfbce582a61c54d72c19f5ac0740d2c5cea4e8020f905f
3
+ metadata.gz: 3039b06d210f7a865957a6eb86b1946e0a7ae2ea63091ada95eed28ad47e8a7b
4
+ data.tar.gz: c5b7ad7943c65cb84eb94b27c6c0b63978bc03f42b14b140df9b52f0caebe24d
5
5
  SHA512:
6
- metadata.gz: 2bf75cf26c5890e8749311e3a65b32d2bd6d8834bbc54e8da77b828b8bbeb32d0e49aa33deda42cb31b733472d4def0044f3a4ef6f69aafa9fae0584952efd39
7
- data.tar.gz: a41d5f22d742e653409a362d58cdf82684b1ded4b671400adf7f184b768eec3acb44f2ec4d9d7f2049c918d9806d8eab355012907576fc4ea470f56c4d62b90a
6
+ metadata.gz: 184707f28d37b10fea94dd4c245dc5143e484b22b089061b3d9efe8cea7b2e48edf38f238dc07dd9fdda728520e482689d505571998c3e52b20913fa828254f6
7
+ data.tar.gz: 00011c9d53005e80ada9eabf45fc4ce98fde60160fb418048a5dd46852ed8db8ee0d4d2c97455605229651d98ed1ce680a70f8a1979382733e66c1853337ad15
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
@@ -5,6 +5,7 @@ module Eazypi
5
5
  module ApiController
6
6
  def self.included(base)
7
7
  base.instance_variable_set(:@operations, [])
8
+ base.include(InstanceMethods)
8
9
  base.extend(ClassMethods)
9
10
  end
10
11
 
@@ -53,5 +54,16 @@ module Eazypi
53
54
  controller_method_name
54
55
  end
55
56
  end
57
+
58
+ # Instance methods to be used in your own API controller
59
+ module InstanceMethods
60
+ def respond_with(object, status: :ok)
61
+ response_type = @current_operation.response_for_response_code(status)
62
+
63
+ response_object_type = response_type.object_type_for_content_type
64
+
65
+ render json: Serializer.serialize_object(response_object_type, object), status: status
66
+ end
67
+ end
56
68
  end
57
69
  end
@@ -44,11 +44,18 @@ module Eazypi
44
44
  @responses.add_response(status_code, &block)
45
45
  end
46
46
 
47
+ def response_for_response_code(response_code)
48
+ response_code = Rack::Utils::SYMBOL_TO_STATUS_CODE[response_code] if response_code.is_a?(Symbol)
49
+
50
+ @responses.response_for_response_code(response_code)
51
+ end
52
+
47
53
  def render(&block)
48
54
  @renderer = block
49
55
  end
50
56
 
51
57
  def call(controller)
58
+ controller.instance_variable_set(:@current_operation, self)
52
59
  controller.instance_exec(&@renderer)
53
60
  end
54
61
 
@@ -9,6 +9,7 @@ module Eazypi
9
9
 
10
10
  def initialize
11
11
  @content = {}
12
+ @object_type = {}
12
13
 
13
14
  super
14
15
  end
@@ -23,6 +24,11 @@ module Eazypi
23
24
  end
24
25
 
25
26
  @content[content_type] = media_type
27
+ @object_type[content_type] = schema
28
+ end
29
+
30
+ def object_type_for_content_type(content_type = "application/json")
31
+ @object_type[content_type]
26
32
  end
27
33
 
28
34
  def collect_components(**kwargs)
@@ -14,6 +14,11 @@ module Eazypi
14
14
  @responses[status_code.to_s] = response
15
15
  end
16
16
 
17
+ def response_for_response_code(response_code)
18
+ # Future improvement could be partial match
19
+ @responses[response_code.to_s]
20
+ end
21
+
17
22
  def collect_components(**kwargs)
18
23
  @responses.each_value do |response|
19
24
  response.collect_components(**kwargs)
@@ -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,6 +49,8 @@ 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
@@ -65,5 +83,19 @@ module Eazypi
65
83
  schema
66
84
  end
67
85
  end
86
+
87
+ def self.serialize_object(type_object, object) # rubocop:disable Metrics/MethodLength
88
+ if type_object.nil?
89
+ nil
90
+ elsif type_object.is_a?(Array)
91
+ object&.map do |value|
92
+ serialize_object(type_object[0], value)
93
+ end
94
+ elsif [String, Integer, Float].include?(type_object)
95
+ object
96
+ else
97
+ type_object.new(object).to_json
98
+ end
99
+ end
68
100
  end
69
101
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Eazypi
4
- VERSION = "0.0.2"
4
+ VERSION = "0.0.4"
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.2
4
+ version: 0.0.4
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-04 00:00:00.000000000 Z
11
+ date: 2024-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack