serega 0.14.0 → 0.15.0

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: f11821b5953500ef9f895ad8c96e97951734615363f3147c623b70519b6199a5
4
- data.tar.gz: 8b03241a9def2e5a8777a75e61062f8b81544e497a1a1e490e085d52f14a326c
3
+ metadata.gz: d780c3d344370b36d9e6db64dfdfa08878bfe32885469610ac2314638c878d87
4
+ data.tar.gz: d282c6466f7b7205a7b524999b85a3e928d79c00ee11445abd26582e0146842c
5
5
  SHA512:
6
- metadata.gz: eb5cb48e74c0e9c8307c6ceb6c47b918eb46ef3c160de90d0eb976239bbc036f1d3fb78219abd5567977f348e3e03d7e492e29140e6d85223fcf14289d794d89
7
- data.tar.gz: acb7623ea317aab640aae70d0a5dfa0c436b706529741b36b15d938ab6af7523576f72ab4633b591b61dcdc38df768818eab3811005c248c3a00d2872cdccc46
6
+ metadata.gz: e2a161487df001b0074d1864770a7dfecd77ef788e187de6e460cd3d2856162cba8777eb807a65a8d4d49471bb50380fc49ffd17f36c16eb52a2ab8b84ed7991
7
+ data.tar.gz: 4a672090d0893ef8d3945b2528fc9861d245833ec4b21074b73481ab7acbf8fa5207c786cad8496bf022070f3341339522bbf4970c7a554cfa543f002f51f504
data/README.md CHANGED
@@ -888,91 +888,14 @@ Look at [select serialized fields](#selecting-fields) for `:hide` usage examples
888
888
  end
889
889
  ```
890
890
 
891
- ### Plugin :openapi
892
-
893
- Helps to build OpenAPI schemas
894
-
895
- This schemas can be easily used with [rswag](https://github.com/rswag/rswag#referenced-parameters-and-schema-definitions)"
896
- gem by adding them to "config.swagger_docs"
897
-
898
- Schemas properties will have no any "type" or other limits specified by default,
899
- you should provide them as new attribute `:openapi` option.
900
-
901
- This plugin adds type "object" or "array" only for relationships and marks
902
- attributes as **required** if they have no `:hide` option set
903
- (manually or automatically).
904
-
905
- After enabling this plugin attributes with :serializer option will have
906
- to have `:many` option set to construct "object" or "array" openapi
907
- property type.
908
-
909
- - constructing all serializers schemas:
910
- `Serega::OpenAPI.schemas`
911
- - constructing specific serializers schemas:
912
- `Serega::OpenAPI.schemas(Serega::OpenAPI.serializers - [MyBaseSerializer])`
913
- - constructing one serializer schema:
914
- `SomeSerializer.openapi_schema`
915
-
916
- ```ruby
917
- class BaseSerializer < Serega
918
- plugin :openapi
919
- end
920
-
921
- class UserSerializer < BaseSerializer
922
- attribute :name, openapi: { type: "string" }
923
-
924
- openapi_properties(
925
- name: { type: :string }
926
- )
927
- end
928
-
929
- class PostSerializer < BaseSerializer
930
- attribute :text, openapi: { type: "string" }
931
- attribute :user, serializer: UserSerializer, many: false
932
- attribute :comments, serializer: PostSerializer, many: true, hide: true
933
-
934
- openapi_properties(
935
- text: { type: :string },
936
- user: { type: 'object' }, # `$ref` added automatically
937
- comments: { type: 'array' } # `items` option with `$ref` added automatically
938
- )
939
- end
940
-
941
- puts Serega::OpenAPI.schemas
942
- # =>
943
- # {
944
- # "PostSerializer" => {
945
- # type: "object",
946
- # properties: {
947
- # text: {type: "string"},
948
- # user: {:$ref => "#/components/schemas/UserSerializer"},
949
- # comments: {type: "array", items: {:$ref => "#/components/schemas/PostSerializer"}}
950
- # },
951
- # required: [:text, :comments],
952
- # additionalProperties: false
953
- # },
954
- # "UserSerializer" => {
955
- # type: "object",
956
- # properties: {
957
- # name: {type: "string"}
958
- # },
959
- # required: [:name],
960
- # additionalProperties: false
961
- # }
962
- # }
963
- ```
964
-
965
891
  ### Plugin :explicit_many_option
966
892
 
967
893
  Plugin requires to add :many option when adding relationships
968
894
  (relationships are attributes with :serializer option specified)
969
895
 
970
- Adding this plugin makes clearer to find if relationship returns array or single
896
+ Adding this plugin makes it clearer to find if relationship returns array or single
971
897
  object
972
898
 
973
- Also plugin `:openapi` load this plugin automatically as it need to know if
974
- relationship is array
975
-
976
899
  ```ruby
977
900
  class BaseSerializer < Serega
978
901
  plugin :explicit_many_option
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.14.0
1
+ 0.15.0
@@ -8,10 +8,7 @@ class Serega
8
8
  # Plugin requires to add :many option when adding relationships
9
9
  # (relationships are attributes with :serializer option specified)
10
10
  #
11
- # Adding this plugin makes clearer to find if relationship returns array or single object
12
- #
13
- # Also some plugins like :openapi load this plugin automatically as they need to know if
14
- # relationship is array
11
+ # Adding this plugin makes it clearer to find if relationship returns array or single object
15
12
  #
16
13
  # @example
17
14
  # class BaseSerializer < Serega
@@ -7,17 +7,34 @@ class Serega
7
7
  # Attribute `:many` option validator
8
8
  #
9
9
  class CheckOptMany
10
- #
11
- # Checks attribute :many option
12
- #
13
- # @param opts [Hash] Attribute options
14
- #
15
- # @raise [SeregaError] SeregaError that option has invalid value
16
- #
17
- # @return [void]
18
- #
19
- def self.call(opts)
20
- Utils::CheckOptIsBool.call(opts, :many)
10
+ class << self
11
+ #
12
+ # Checks attribute :many option
13
+ #
14
+ # @param opts [Hash] Attribute options
15
+ #
16
+ # @raise [SeregaError] SeregaError that option has invalid value
17
+ #
18
+ # @return [void]
19
+ #
20
+ def call(opts)
21
+ return unless opts.key?(:many)
22
+
23
+ check_many_option_makes_sence(opts)
24
+ Utils::CheckOptIsBool.call(opts, :many)
25
+ end
26
+
27
+ private
28
+
29
+ def check_many_option_makes_sence(opts)
30
+ return if many_option_makes_sence?(opts)
31
+
32
+ raise SeregaError, "Option :many can be provided only together with :serializer or :batch option"
33
+ end
34
+
35
+ def many_option_makes_sence?(opts)
36
+ opts[:serializer] || opts[:batch]
37
+ end
21
38
  end
22
39
  end
23
40
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serega
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Glushkov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-24 00:00:00.000000000 Z
11
+ date: 2023-08-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  JSON Serializer
@@ -74,9 +74,6 @@ files:
74
74
  - lib/serega/plugins/metadata/validations/check_opt_hide_nil.rb
75
75
  - lib/serega/plugins/metadata/validations/check_opts.rb
76
76
  - lib/serega/plugins/metadata/validations/check_path.rb
77
- - lib/serega/plugins/openapi/lib/modules/config.rb
78
- - lib/serega/plugins/openapi/lib/openapi_config.rb
79
- - lib/serega/plugins/openapi/openapi.rb
80
77
  - lib/serega/plugins/preloads/lib/format_user_preloads.rb
81
78
  - lib/serega/plugins/preloads/lib/modules/attribute.rb
82
79
  - lib/serega/plugins/preloads/lib/modules/attribute_normalizer.rb
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Serega
4
- module SeregaPlugins
5
- module OpenAPI
6
- #
7
- # Config class additional/patched instance methods
8
- #
9
- # @see Serega::SeregaConfig
10
- #
11
- module ConfigInstanceMethods
12
- #
13
- # Returns openapi plugin config
14
- #
15
- # @return [Serega::SeregaPlugins::OpenAPI::OpenAPIConfig] configuration for openapi plugin
16
- #
17
- def openapi
18
- @openapi ||= OpenAPIConfig.new(self.class.serializer_class, opts.fetch(:openapi))
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,101 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Serega
4
- module SeregaPlugins
5
- module OpenAPI
6
- #
7
- # OpenAPI plugin config
8
- #
9
- class OpenAPIConfig
10
- attr_reader :serializer_class, :opts
11
-
12
- def initialize(serializer_class, opts)
13
- @serializer_class = serializer_class
14
- @opts = opts
15
- end
16
-
17
- #
18
- # Saves new properties
19
- #
20
- # @param new_properties [Hash] new properties
21
- #
22
- # @return [Hash] OpenAPI properties
23
- #
24
- def properties(new_properties = FROZEN_EMPTY_HASH)
25
- properties = opts[:properties]
26
- return properties if new_properties.empty?
27
-
28
- new_properties = SeregaUtils::EnumDeepDup.call(new_properties)
29
- symbolize_keys!(new_properties)
30
-
31
- new_properties.each do |attribute_name, new_attribute_properties|
32
- check_attribute_exists(attribute_name)
33
- check_properties_is_a_hash(attribute_name, new_attribute_properties)
34
-
35
- properties[attribute_name] = symbolize_keys!(new_attribute_properties)
36
- end
37
- end
38
-
39
- #
40
- # @return [#call] builder of `$ref` attribute
41
- #
42
- def ref_builder
43
- opts[:ref_builder]
44
- end
45
-
46
- #
47
- # Sets new $ref option builder
48
- #
49
- # @param builder [#call] Callable object that accepts serializer_class and constructs $ref option string
50
- #
51
- # @return Specified new builder
52
- #
53
- def ref_builder=(builder)
54
- raise SeregaError, "ref_builder must respond to #call" unless builder.respond_to?(:call)
55
- opts[:ref_builder] = builder
56
- end
57
-
58
- #
59
- # @return [#call] builder of schema name
60
- #
61
- def schema_name_builder
62
- opts[:schema_name_builder]
63
- end
64
-
65
- #
66
- # Sets new schema_name_builder
67
- #
68
- # @param builder [#call] Callable object that accepts serializer_class and
69
- # constructs schema name to use in schemas list and in $ref option
70
- #
71
- # @return Specified new builder
72
- #
73
- def schema_name_builder=(builder)
74
- raise SeregaError, "schema_name_builder must respond to #call" unless builder.respond_to?(:call)
75
- opts[:schema_name_builder] = builder
76
- end
77
-
78
- private
79
-
80
- def check_attribute_exists(attribute_name)
81
- return if serializer_class.attributes.key?(attribute_name)
82
-
83
- raise SeregaError, "No attribute with name :#{attribute_name}"
84
- end
85
-
86
- def check_properties_is_a_hash(attribute_name, new_attribute_properties)
87
- return if new_attribute_properties.is_a?(Hash)
88
-
89
- raise SeregaError, "Property #{attribute_name} value must be a Hash," \
90
- " but #{new_attribute_properties.inspect} was provided"
91
- end
92
-
93
- def symbolize_keys!(opts)
94
- opts.transform_keys! do |key|
95
- key.to_sym
96
- end
97
- end
98
- end
99
- end
100
- end
101
- end
@@ -1,245 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Serega
4
- #
5
- # Utility class to build OpenAPI schemas
6
- #
7
- class OpenAPI
8
- #
9
- # Constructs OpenAPI schemas for multiple serializers
10
- #
11
- # @params serializers [Class<Serega>] Serializers tobuild schemas,
12
- # by default it is all serializers with :openapi plugin enabled
13
- #
14
- # @return [Hash] Schemas hash
15
- #
16
- def self.schemas(serializers = self.serializers)
17
- serializers.each_with_object({}) do |serializer_class, schemas|
18
- schema = serializer_class.openapi_schema
19
- schema_name = serializer_class.openapi_schema_name
20
- schemas[schema_name] = schema
21
- end
22
- end
23
-
24
- #
25
- # Returns list of serializers with :openapi plugin
26
- #
27
- def self.serializers
28
- @serializers ||= []
29
- end
30
- end
31
-
32
- module SeregaPlugins
33
- #
34
- # Plugin :openapi
35
- #
36
- # Helps to build OpenAPI schemas
37
- #
38
- # This schemas can be easielty used with "rswag" gem by adding them to "config.swagger_docs"
39
- # https://github.com/rswag/rswag#referenced-parameters-and-schema-definitions
40
- #
41
- # This plugin only adds type "object" or "array" for relationships and marks
42
- # attributes as **required** if they have no :hide option set.
43
- #
44
- # OpenAPI properties will have no any "type" or other options specified by default,
45
- # you should provide them in 'YourSerializer.openapi_properties' method.
46
- # `openapi_properties` can be specified multiple time, in this case they wil be merged.
47
- #
48
- # After enabling this plugin attributes with :serializer option will have
49
- # to have :many option set to construct "object" or "array" openapi type for relationships.
50
- #
51
- # OpenAPI `$ref` property will be added automatically for all relationships.
52
- #
53
- # Example constructing all serializers schemas:
54
- # `Serega::OpenAPI.schemas`
55
- #
56
- # Example constructing specific serializers schemas:
57
- # `Serega::OpenAPI.schemas(Serega::OpenAPI.serializers - [MyBaseSerializer])`
58
- #
59
- # Example constructing one serializer schema:
60
- # `SomeSerializer.openapi_schema`
61
- #
62
- # @example
63
- # class BaseSerializer < Serega
64
- # plugin :openapi
65
- # end
66
- #
67
- # class UserSerializer < BaseSerializer
68
- # attribute :name
69
- #
70
- # openapi_properties(
71
- # name: { type: :string }
72
- # )
73
- # end
74
- #
75
- # class PostSerializer < BaseSerializer
76
- # attribute :text
77
- # attribute :user, serializer: UserSerializer, many: false
78
- # attribute :comments, serializer: PostSerializer, many: true, hide: true
79
- #
80
- # openapi_properties(
81
- # text: { type: :string },
82
- # user: { type: 'object' }, # `$ref` option will be added automatically when constructing schema
83
- # comments: { type: 'array' } # `items` option with `$ref` will be added automatically when constructing schema
84
- # )
85
- # end
86
- #
87
- # puts Serega::OpenAPI.schemas
88
- # =>
89
- # {
90
- # "PostSerializer" => {
91
- # type: "object",
92
- # properties: {
93
- # text: {type: "string"},
94
- # user: {:$ref => "#/components/schemas/UserSerializer"},
95
- # comments: {type: "array", items: {:$ref => "#/components/schemas/PostSerializer"}}
96
- # },
97
- # required: [:text, :comments],
98
- # additionalProperties: false
99
- # },
100
- # "UserSerializer" => {
101
- # type: "object",
102
- # properties: {
103
- # name: {type: "string"}
104
- # },
105
- # required: [:name],
106
- # additionalProperties: false
107
- # }
108
- # }
109
- #
110
- module OpenAPI
111
- # Builder for schema name (used is schemas list). Returns serializer class name
112
- DEFAULT_SCHEMA_NAME_BUILDER = ->(serializer_class) { serializer_class.name }
113
-
114
- # Builder for $ref openapi property
115
- DEFAULT_REF_BUILDER = ->(serializer_class) { "#/components/schemas/#{serializer_class.openapi_schema_name}" }
116
-
117
- # @return [Symbol] Plugin name
118
- def self.plugin_name
119
- :openapi
120
- end
121
-
122
- # Checks requirements and loads additional plugins
123
- #
124
- # @param serializer_class [Class<Serega>] Current serializer class
125
- # @param opts [Hash] loaded plugins opts
126
- #
127
- # @return [void]
128
- #
129
- def self.before_load_plugin(serializer_class, **opts)
130
- unless serializer_class.plugin_used?(:explicit_many_option)
131
- serializer_class.plugin :explicit_many_option
132
- end
133
- end
134
-
135
- #
136
- # Applies plugin code to specific serializer
137
- #
138
- # @param serializer_class [Class<Serega>] Current serializer class
139
- # @param _opts [Hash] Loaded plugins options
140
- #
141
- # @return [void]
142
- #
143
- def self.load_plugin(serializer_class, **opts)
144
- require_relative "./lib/modules/config"
145
- require_relative "./lib/openapi_config"
146
-
147
- serializer_class.extend(ClassMethods)
148
- serializer_class::SeregaConfig.include(ConfigInstanceMethods)
149
-
150
- config = serializer_class.config
151
- config.opts[:openapi] = {properties: {}}
152
- openapi_config = serializer_class.config.openapi
153
- openapi_config.schema_name_builder = opts[:schema_name_builder] || DEFAULT_SCHEMA_NAME_BUILDER
154
- openapi_config.ref_builder = opts[:ref_builder] || DEFAULT_REF_BUILDER
155
- end
156
-
157
- #
158
- # Adds config options and runs other callbacks after plugin was loaded
159
- #
160
- # @param serializer_class [Class<Serega>] Current serializer class
161
- # @param opts [Hash] loaded plugins opts
162
- #
163
- # @return [void]
164
- #
165
- def self.after_load_plugin(serializer_class, **opts)
166
- Serega::OpenAPI.serializers << serializer_class unless serializer_class.equal?(Serega)
167
- end
168
-
169
- #
170
- # Serega additional/patched class methods
171
- #
172
- # @see Serega
173
- #
174
- module ClassMethods
175
- #
176
- # OpenAPI schema for current serializer
177
- #
178
- def openapi_schema
179
- properties = SeregaUtils::EnumDeepDup.call(openapi_properties)
180
- required_properties = []
181
-
182
- attributes.each do |attribute_name, attribute|
183
- add_openapi_property(properties, attribute_name, attribute)
184
- add_openapi_required_property(required_properties, attribute_name, attribute)
185
- end
186
-
187
- {
188
- type: "object",
189
- properties: properties,
190
- required: required_properties,
191
- additionalProperties: false
192
- }
193
- end
194
-
195
- #
196
- # Adds new OpenAPI properties and returns all properties
197
- #
198
- # @param props [Hash] Specifies new properties
199
- #
200
- # @return [Hash] Specified OpenAPI properties
201
- #
202
- def openapi_properties(props = FROZEN_EMPTY_HASH)
203
- config.openapi.properties(props)
204
- end
205
-
206
- #
207
- # Builds OpenAPI schema name using configured builder
208
- #
209
- # @return [String] OpenAPI schema name
210
- #
211
- def openapi_schema_name
212
- config.openapi.schema_name_builder.call(self)
213
- end
214
-
215
- private
216
-
217
- def inherited(subclass)
218
- super
219
- Serega::OpenAPI.serializers << subclass
220
- end
221
-
222
- def add_openapi_property(properties, attribute_name, attribute)
223
- property = properties[attribute_name] ||= {}
224
- return unless attribute.relation?
225
-
226
- ref = attribute.serializer.config.openapi.ref_builder.call(attribute.serializer)
227
-
228
- if attribute.many
229
- property[:type] = "array"
230
- property[:items] ||= {}
231
- property[:items][:$ref] ||= ref
232
- else
233
- property[:$ref] ||= ref
234
- end
235
- end
236
-
237
- def add_openapi_required_property(required_properties, attribute_name, attribute)
238
- required_properties << attribute_name unless attribute.hide
239
- end
240
- end
241
- end
242
-
243
- register_plugin(OpenAPI.plugin_name, OpenAPI)
244
- end
245
- end