dry-swagger 0.5.1 → 0.6.2

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: 3b612143bf3038b32981bae55874524220f769bfe7db95ee1fc2be928f563f73
4
- data.tar.gz: 02e71a27f38fafae4f6db24d267157467dbe1889649caf036b3eddafa8b7ef27
3
+ metadata.gz: 9b26879187416eeb9a9bafee3cb7f7cfc11cf507b7c9684fc8415f12ed246bfd
4
+ data.tar.gz: dea3839fce17641081fc569c29f32d758eccb5bfe2b3e9139e35b9495104be47
5
5
  SHA512:
6
- metadata.gz: 9c3da6167caaf0f60a5d4b6f07aa00b1c964c19c8b8cc7508c7d59a3e266a34c5f54c66644030a3048e2713092ca164f4d1f82315a09a8989bfc702486bc05d8
7
- data.tar.gz: 10c946ec34aef062dccccfedfa6fe6fb8b6ba9cfb09d0a434d7cf22d879a60177632f28c082b0dd81091cccf66204b4ded6526888b60b37234c8b8a288af0bc7
6
+ metadata.gz: c1526dbb96d90dfa3631d92289e861d66af20bd7709a4e79d214275699e611f22739e660ea1ec4a3a7c93eb19bf92141d8dd2e5fce4f177567db50a07a6b3d37
7
+ data.tar.gz: 0a51759965cd85fd48a5177ddb68b8999a3b2b63eb6d8108e4b6d39ae07696b9b46cc095ff01f470fb413b956196c94a9d7655eb7cc1d64419dfcb6268d9ea84
data/.gitignore CHANGED
@@ -10,3 +10,4 @@
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
12
  .idea/
13
+ config/
data/Gemfile CHANGED
@@ -7,3 +7,4 @@ gem "rake", "~> 12.0"
7
7
  gem "rspec", "~> 3.0"
8
8
  gem "dry-validation"
9
9
  gem "dry-struct"
10
+ gem 'i18n'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dry-swagger (0.5.1)
4
+ dry-swagger (0.6.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -46,6 +46,8 @@ GEM
46
46
  dry-equalizer (~> 0.2)
47
47
  dry-initializer (~> 3.0)
48
48
  dry-schema (~> 1.5, >= 1.5.2)
49
+ i18n (1.8.10)
50
+ concurrent-ruby (~> 1.0)
49
51
  ice_nine (0.11.2)
50
52
  rake (12.3.3)
51
53
  rspec (3.10.0)
@@ -69,6 +71,7 @@ DEPENDENCIES
69
71
  dry-struct
70
72
  dry-swagger!
71
73
  dry-validation
74
+ i18n
72
75
  rake (~> 12.0)
73
76
  rspec (~> 3.0)
74
77
 
data/README.md CHANGED
@@ -15,269 +15,269 @@ And then execute:
15
15
 
16
16
  bundle install
17
17
 
18
- Or install it yourself as:
19
-
20
- gem install dry-swagger
21
-
22
- ## Usage
23
- ## Dry::Validation::Contract
24
- class Contract < Dry::Validation::Contract
25
- json do
26
- required(:required_field).value(:str?)
27
- required(:required_nullable_field).maybe(:str?)
28
- required(:required_filled_field).filled(:str?)
29
-
30
- optional(:optional_field).value(:str?)
31
- optional(:optional_nullable_field).maybe(:str?)
32
- optional(:optional_filled_field).filled(:str?)
33
- end
34
- end
18
+ After installing, execute the following command:
35
19
 
36
- Dry::Swagger::ContractParser.new.call(Contract).to_swagger
37
- => {
38
- "type": "object",
39
- "properties": {
40
- "required_field": {
41
- "type": "string",
42
- "nullable": false
43
- },
44
- "required_nullable_field": {
45
- "type": "string",
46
- "nullable": true
47
- },
48
- "required_filled_field": {
49
- "type": "string",
50
- "nullable": false
51
- },
52
- "optional_field": {
53
- "type": "string",
54
- "nullable": false
55
- },
56
- "optional_nullable_field": {
57
- "type": "string",
58
- "nullable": true
59
- },
60
- "optional_filled_field": {
61
- "type": "string",
62
- "nullable": false
63
- }
64
- },
65
- "required": [
66
- "required_field",
67
- "required_nullable_field",
68
- "required_filled_field"
69
- ]
70
- }
71
- #### With nested fields - hash or array
72
- class Contract < Dry::Validation::Contract
73
- json do
74
- required(:array_field).array(:int?)
75
- required(:array_of_hash).array(:hash) do
76
- required(:field).value(:str?)
77
- end
78
- required(:hash_field).hash do
79
- required(:field).value(:str?)
20
+ rake dry-swagger:install
21
+
22
+ This will generate configuration files in your project under `project/config`. See Configuration section for more details.
23
+
24
+ ##Usage
25
+
26
+ ####With Dry::Validation::Contract
27
+ Lets say we have the following Dry::Validation::Contract definition:
28
+
29
+ class TestContract < Dry::Validation::Contract
30
+ params do
31
+ required(:some_field).value(:str?, min_size?: 5, max_size?: 10)
32
+ required(:some_array_of_objects).array(:hash) do
33
+ required(:some_nested_attribute).value(:str?)
34
+ end
35
+ required(:some_array_of_integers).array(:int?)
36
+ required(:dto).value(:hash) do
37
+ optional(:some_nested_attribute).maybe(:str?)
38
+ end
80
39
  end
81
- end
82
40
  end
83
41
 
84
- Dry::Swagger::ContractParser.new.call(Contract).to_swagger
85
- => {
86
- "type": "object",
87
- "properties": {
88
- "array_field": {
89
- "type": "array",
90
- "items": {
91
- "type": "integer"
92
- }
93
- },
94
- "array_of_hash": {
95
- "type": "array",
96
- "items": {
97
- "type": "object",
98
- "properties": {
99
- "field": {
100
- "type": "string",
101
- "x-nullable": false
102
- }
103
- },
104
- "required": [
105
- "field"
106
- ]
107
- }
108
- },
109
- "hash_field": {
110
- "type": "object",
111
- "properties": {
112
- "field": {
113
- "type": "string",
114
- "x-nullable": false
115
- }
116
- },
117
- "required": [
118
- "field"
119
- ]
120
- }
121
- },
122
- "required": [
123
- "array_field",
124
- "array_of_hash",
125
- "hash_field"
126
- ]
127
- }
42
+ parser = Dry::Swagger::ContractParser.new
128
43
 
129
- ### With Dry::Struct
130
- class DTO < Dry::Struct
131
- attribute :required_string, Types::String
132
- attribute :required_nullable_string, Types::String.optional
133
- attribute :required_string_with_enum, Types::String.enum('enum1')
134
- attribute? :optional_string, Types::String
135
- attribute? :optional_nullable_string, Types::String.optional
136
- end
44
+ `parser.call(TestContract)` will set the `keys` of the `parser` object to:
137
45
 
138
- Dry::Swagger::StructParser.new.call(DTO).to_swagger
139
- => {
140
- "type": "object",
141
- "properties": {
142
- "required_string": {
143
- "type": "string",
144
- "x-nullable": false
145
- },
146
- "required_nullable_string": {
147
- "type": "string",
148
- "x-nullable": true
149
- },
150
- "required_string_with_enum": {
151
- "type": "string",
152
- "enum": [
153
- "enum1"
154
- ],
155
- "x-nullable": false
156
- },
157
- "optional_string": {
158
- "type": "string",
159
- "x-nullable": false
160
- },
161
- "optional_nullable_string": {
162
- "type": "string",
163
- "x-nullable": true
164
- }
46
+ {
47
+ :some_field => {
48
+ :required => true,
49
+ :type => "string",
50
+ :description => "Minimum size: 5, Maximum size: 10"
51
+ },
52
+ :some_array_of_objects => {
53
+ :required => true,
54
+ :array => true,
55
+ :type => "array",
56
+ :keys => {
57
+ :some_nested_attribute => {
58
+ :required=>true, :type=>"string"
59
+ }
60
+ }
165
61
  },
166
- "required": [
167
- "required_string",
168
- "required_nullable_string",
169
- "required_string_with_enum"
170
- ]
171
- }
172
- #### With nested fields
173
- class NestedDTO < Dry::Struct
174
- attribute :required_string, Types::String
175
- attribute :required_nullable_string, Types::String.optional
176
- attribute :required_string_with_enum, Types::String.enum('enum1')
177
- attribute? :optional_string, Types::String
178
- attribute? :optional_nullable_string, Types::String.optional
179
- end
180
-
181
- class DTO < Dry::Struct
182
- attribute :array_of_integer, Types::Array.of(Types::Integer)
183
- attribute :array_of_objects, Types::Array.of(NestedDTO)
184
- attribute :dto, NestedDTO
185
- end
62
+ :some_array_of_integers => {
63
+ :required=>true,
64
+ :array=>true,
65
+ :type=>"integer"
66
+ },
67
+ :dto => {
68
+ :required => true,
69
+ :type => "hash",
70
+ :keys => {
71
+ :some_nested_attribute => {
72
+ :required => false,
73
+ :"x-nullable"=>true,
74
+ :type=>"string"
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ As we can see, the `ContractParser` goes through all the params defined in the
81
+ schema and generates a hash. The hash is saved in the `keys` attribute of the parser,
82
+ so that we can call `to_swagger` later.
83
+
84
+ The required key in our result will be set to `true` if the field is defined as
85
+ `required(:field_name)`, and `false` if defined as `optional(:field_name)`.
86
+
87
+ The "x-nullable" key depends on whether we have defined the field as value, maybe or filled.
88
+
89
+ For nested objects like array of objects or hash, we add a keys field with a definition
90
+ for each field inside the nested hash.
91
+
92
+ If the field is an array of primitive type, the type field will equal to the primitive type, and a
93
+ array flag will be set on the field.
94
+
95
+ Calling `parser.to_swagger` will give the following result:
186
96
 
187
- Dry::Swagger::StructParser.new.call(DTO).to_swagger
188
- => {
97
+ {
189
98
  "type": "object",
190
99
  "properties": {
191
- "array_of_integer": {
192
- "type": "array",
193
- "items": {
194
- "type": "integer"
195
- },
100
+ "some_field": {
101
+ "type": "string",
102
+ "description": "Minimum size: 5, Maximum size: 10",
196
103
  "x-nullable": false
197
104
  },
198
- "array_of_objects": {
105
+ "some_array_of_objects": {
199
106
  "type": "array",
200
107
  "items": {
201
108
  "type": "object",
202
109
  "properties": {
203
- "required_string": {
204
- "type": "string",
205
- "x-nullable": false
206
- },
207
- "required_nullable_string": {
208
- "type": "string",
209
- "x-nullable": true
210
- },
211
- "required_string_with_enum": {
212
- "type": "string",
213
- "enum": [
214
- "enum1"
215
- ],
216
- "x-nullable": false
217
- },
218
- "optional_string": {
110
+ "some_nested_attribute": {
219
111
  "type": "string",
220
112
  "x-nullable": false
221
- },
222
- "optional_nullable_string": {
223
- "type": "string",
224
- "x-nullable": true
225
113
  }
226
114
  },
227
115
  "required": [
228
- "required_string",
229
- "required_nullable_string",
230
- "required_string_with_enum"
231
- ]
116
+ "some_nested_attribute"
117
+ ],
118
+ "x-nullable": false
119
+ },
120
+ "x-nullable": false
121
+ },
122
+ "some_array_of_integers": {
123
+ "type": "array",
124
+ "items": {
125
+ "type": "integer",
126
+ "x-nullable": false
232
127
  },
233
128
  "x-nullable": false
234
129
  },
235
130
  "dto": {
236
131
  "type": "object",
237
132
  "properties": {
238
- "required_string": {
239
- "type": "string",
240
- "x-nullable": false
241
- },
242
- "required_nullable_string": {
243
- "type": "string",
244
- "x-nullable": true
245
- },
246
- "required_string_with_enum": {
247
- "type": "string",
248
- "enum": [
249
- "enum1"
250
- ],
251
- "x-nullable": false
252
- },
253
- "optional_string": {
254
- "type": "string",
255
- "x-nullable": false
256
- },
257
- "optional_nullable_string": {
133
+ "some_nested_attribute": {
258
134
  "type": "string",
259
135
  "x-nullable": true
260
136
  }
261
137
  },
262
138
  "required": [
263
- "required_string",
264
- "required_nullable_string",
265
- "required_string_with_enum"
139
+
266
140
  ],
267
141
  "x-nullable": false
268
142
  }
269
143
  },
270
144
  "required": [
271
- "array_of_integer",
272
- "array_of_objects",
145
+ "some_field",
146
+ "some_array_of_objects",
147
+ "some_array_of_integers",
273
148
  "dto"
274
149
  ]
275
150
  }
276
- ## Overriding fields on run time
277
- You can also modify the fields during runtime by passing a block after the .call() method.
278
151
 
279
- For example:
152
+ ####With Dry::Struct
153
+ The `Dry::Swagger::StructParser` works the same as the contract parser.
154
+
155
+ The required key depends on whether we define the field as attribute or attribute?
156
+
157
+ The "x-nullable" key depends on whether we define the type as Type or Type.optional.
158
+
159
+ For more complex types, for example DTO1 | DTO2 or Types::Array.of(DTO1 | DTO2),
160
+ the parser converts the field value to an array of both schemas.
161
+
162
+ Example:
163
+
164
+ class DTO1 < Dry::Struct
165
+ attribute :dto1_field, Types::String
166
+ end
167
+
168
+ class DTO2 < Dry::Struct
169
+ attribute :dto2_field, Types::String
170
+ end
171
+
172
+ class DTO < Dry::Struct
173
+ attribute :dynamic_dto, DTO1 | DTO2
174
+ end
175
+ parser = Dry::Swagger::StructParser.new
176
+
177
+ parser.call(DTO)
178
+ => {
179
+ "dynamic_dto": [ # ARRAY
180
+ {
181
+ "type": "hash",
182
+ "required": true,
183
+ "x-nullable": false,
184
+ "keys": {
185
+ "dto1_field": {
186
+ "type": "string",
187
+ "required": true,
188
+ "x-nullable": false
189
+ }
190
+ }
191
+ },
192
+ {
193
+ "type": "hash",
194
+ "required": true,
195
+ "x-nullable": false,
196
+ "keys": {
197
+ "dto2_field": {
198
+ "type": "string",
199
+ "required": true,
200
+ "x-nullable": false
201
+ }
202
+ }
203
+ }
204
+ ]
205
+ }
206
+
207
+ Calling `parser.to_swagger` will give the following result:
280
208
 
209
+ {
210
+ "type": "object",
211
+ "properties": {
212
+ "dynamic_dto": {
213
+ "type": "object",
214
+ "properties": {
215
+ "definition_1": {
216
+ "type": "object",
217
+ "properties": {
218
+ "dto1_field": {
219
+ "type": "string",
220
+ "x-nullable": false
221
+ }
222
+ },
223
+ "required": [
224
+ "dto1_field"
225
+ ],
226
+ "x-nullable": false
227
+ },
228
+ "definition_2": {
229
+ "type": "object",
230
+ "properties": {
231
+ "dto2_field": {
232
+ "type": "string",
233
+ "x-nullable": false
234
+ }
235
+ },
236
+ "required": [
237
+ "dto2_field"
238
+ ],
239
+ "x-nullable": false
240
+ }
241
+ },
242
+ "example": "Dynamic Field. See Model Definitions",
243
+ "oneOf": [
244
+ {
245
+ "type": "object",
246
+ "properties": {
247
+ "dto1_field": {
248
+ "type": "string",
249
+ "x-nullable": false
250
+ }
251
+ },
252
+ "required": [
253
+ "dto1_field"
254
+ ],
255
+ "x-nullable": false
256
+ },
257
+ {
258
+ "type": "object",
259
+ "properties": {
260
+ "dto2_field": {
261
+ "type": "string",
262
+ "x-nullable": false
263
+ }
264
+ },
265
+ "required": [
266
+ "dto2_field"
267
+ ],
268
+ "x-nullable": false
269
+ }
270
+ ]
271
+ }
272
+ },
273
+ "required": [
274
+ "dynamic_dto"
275
+ ]
276
+ }
277
+
278
+ ## Overriding fields
279
+ You can also modify the fields by passing a block after the .call() method.
280
+
281
281
  Dry::Swagger::StructParser.new.call(DTO) do |it|
282
282
  # types = string/integer/hash/array
283
283
 
@@ -311,26 +311,12 @@ For example:
311
311
  }
312
312
 
313
313
  end.to_swagger()
314
- ## Custom Configuration For Your Project
315
- You can override default configurations by creating a file in config/initializers/dry-swagger.rb and changing the following values.
316
-
317
- Dry::Swagger::Config::StructConfiguration.configuration do |config|
318
- config.enable_required_validation = true / false
319
- config.enable_nullable_validation = true / false
320
- config.enable_enums = true / false
321
- config.enable_descriptions = true / false
322
- config.nullable_type = :"x-nullable" / :nullable
323
- end
324
314
 
325
- Dry::Swagger::Config::ContractConfiguration.configuration do |config|
326
- config.enable_required_validation = true / false
327
- config.enable_nullable_validation = true / false
328
- config.enable_enums = true / false
329
- config.enable_descriptions = true / false
330
- config.nullable_type = :"x-nullable" / :nullable
331
- end
332
-
333
- By default, all these settings are true, and nullable_type is :"x-nullable".
315
+ ##Custom Configuration For Your Project
316
+ You can override default configurations by changing the values in the `config/initializers/dry-swagger.rb` file generated from the rake command in the Installation section.
317
+
318
+ To modify the descriptions for the Contracts, modify the values in `config/locale/dry-swagger.yml`.
319
+
334
320
  ## Development
335
321
 
336
322
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/lib/dry/swagger.rb CHANGED
@@ -7,8 +7,11 @@ require 'dry/swagger/errors/missing_type_error'
7
7
  require 'dry/swagger/config/configuration'
8
8
  require 'dry/swagger/config/contract_configuration'
9
9
  require 'dry/swagger/config/struct_configuration'
10
+ require 'i18n'
10
11
 
11
12
  module Dry
12
13
  module Swagger
14
+ ::I18n.load_path << Dir[File.expand_path("config/locales") + "/*.yml"]
15
+ require 'my_gem/railtie' if defined?(Rails)
13
16
  end
14
17
  end
@@ -116,18 +116,8 @@ module Dry
116
116
  end
117
117
  end
118
118
 
119
- def predicate_description(name, validation)
120
- case name
121
- when 'eql?' then "Must be equal to #{validation}"
122
- when 'max_size?' then "Maximum size: #{validation}"
123
- when 'min_size?' then "Minimum size: #{validation}"
124
- when 'gteq?' then "Greater or equal #{validation}"
125
- when 'gt?' then "Greater than #{validation}"
126
- when 'lt?' then "Lower than #{validation}"
127
- when 'lteq?' then "Lower than or equal to #{validation}"
128
- else
129
- ''
130
- end
119
+ def predicate_description(name, value)
120
+ ::I18n.t("contract.descriptions.#{name}", value: value, default: '')
131
121
  end
132
122
 
133
123
  def to_swagger
@@ -17,83 +17,90 @@ module Dry
17
17
 
18
18
  def generate_documentation(fields)
19
19
  documentation = { properties: {}, required: [] }
20
- fields.each do |field_name, attributes_hash|
21
- documentation[:properties][field_name] = generate_field_properties(attributes_hash)
22
- if attributes_hash.is_a?(Hash)
23
- documentation[:required] << field_name if attributes_hash.fetch(:required, true) && @config.enable_required_validation
20
+ fields.each do |field_name, definition|
21
+ documentation[:properties][field_name] = generate_field_properties(definition)
22
+ if definition.is_a?(Hash)
23
+ documentation[:required] << field_name if definition.fetch(:required, true) && @config.enable_required_validation
24
24
  else
25
- documentation[:required] << field_name if attributes_hash[0].fetch(:required, true) && @config.enable_required_validation
25
+ documentation[:required] << field_name if definition[0].fetch(:required, true) && @config.enable_required_validation
26
26
  end
27
27
 
28
28
  rescue Errors::MissingTypeError => e
29
- raise StandardError.new e.message % { field_name: field_name, valid_types: SWAGGER_FIELD_TYPE_DEFINITIONS.keys, attributes_hash: attributes_hash }
29
+ raise StandardError.new e.message % { field_name: field_name, valid_types: SWAGGER_FIELD_TYPE_DEFINITIONS.keys, definition: definition }
30
30
  rescue Errors::MissingHashSchemaError => e
31
- raise StandardError.new e.message % { field_name: field_name, valid_types: SWAGGER_FIELD_TYPE_DEFINITIONS.keys, attributes_hash: attributes_hash }
31
+ raise StandardError.new e.message % { field_name: field_name, valid_types: SWAGGER_FIELD_TYPE_DEFINITIONS.keys, definition: definition }
32
32
  end
33
33
 
34
34
  { :type => :object, :properties => documentation[:properties], :required => documentation[:required] }
35
35
  end
36
36
 
37
- def generate_field_properties(attributes_hash)
38
- if attributes_hash.is_a?(Array)
39
- properties = {}
40
- attributes_hash.each_with_index do |_, index|
41
- properties["definition_#{index + 1}"] = generate_field_properties(attributes_hash[index])
42
- end
43
- if attributes_hash[0][:type] == 'array'
44
- attributes_hash.each { |definition| definition[:type] = 'hash'}
45
- {
46
- type: :array,
47
- items: {
48
- type: :object,
49
- properties: properties,
50
- oneOf: attributes_hash.map{ |it| generate_field_properties(it) },
51
- example: 'Dynamic Field. See Model Definitions'
52
- },
53
- }
54
- else
55
- {
56
- oneOf: attributes_hash.map{ |it| generate_field_properties(it) },
57
- type: :object,
58
- properties: properties,
59
- example: 'Dynamic Field. See Model Definitions'
60
- }
61
- end
62
- else
63
- if attributes_hash[:type] == 'array'
64
- items = generate_documentation(attributes_hash.fetch(:keys))
65
- items = @config.enable_nullable_validation ?
66
- items.merge(@config.nullable_type => attributes_hash.fetch(@config.nullable_type, false)) :
67
- items.merge(@config.nullable_type => true)
68
- documentation = { type: :array, items: items }
69
- elsif attributes_hash[:array] && attributes_hash.fetch(:type) != 'array'
70
- items = SWAGGER_FIELD_TYPE_DEFINITIONS.fetch(attributes_hash.fetch(:type))
71
- items = @config.enable_nullable_validation ?
72
- items.merge(@config.nullable_type => attributes_hash.fetch(@config.nullable_type, false)) :
73
- items.merge(@config.nullable_type => true)
74
- documentation = { type: :array, items: items }
75
- elsif attributes_hash[:type] == 'hash'
76
- raise Errors::MissingHashSchemaError.new unless attributes_hash[:keys]
77
- documentation = generate_documentation(attributes_hash.fetch(:keys))
78
- else
79
- documentation = SWAGGER_FIELD_TYPE_DEFINITIONS.fetch(attributes_hash.fetch(:type))
80
- if attributes_hash[:enum] && @config.enable_enums
81
- documentation = documentation.merge(enum: attributes_hash.fetch(:enum))
82
- end
83
-
84
- if attributes_hash[:description] && @config.enable_descriptions
85
- documentation = documentation.merge(description: attributes_hash.fetch(:description))
86
- end
87
- end
37
+ def generate_field_properties(definition)
38
+ return generate_for_sti_type(definition) if definition.is_a?(Array)
88
39
 
89
- @config.enable_nullable_validation ?
90
- documentation.merge(@config.nullable_type => attributes_hash.fetch(@config.nullable_type, false)) :
91
- documentation.merge(@config.nullable_type => true)
40
+ if definition[:type] == 'array' || definition[:array]
41
+ documentation = generate_for_array(definition)
42
+ elsif definition[:type] == 'hash'
43
+ documentation = generate_for_hash(definition)
44
+ else
45
+ documentation = generate_for_primitive_type(definition)
92
46
  end
47
+ @config.enable_nullable_validation ?
48
+ documentation.merge(@config.nullable_type => definition.fetch(@config.nullable_type, false)) :
49
+ documentation.merge(@config.nullable_type => true)
93
50
 
94
51
  rescue KeyError
95
52
  raise Errors::MissingTypeError.new
96
53
  end
54
+
55
+ def generate_for_sti_type(definition)
56
+ properties = {}
57
+
58
+ definition.each_with_index do |_, index|
59
+ properties["definition_#{index + 1}"] = generate_field_properties(definition[index])
60
+ end
61
+
62
+ documentation = {
63
+ type: :object,
64
+ properties: properties,
65
+ example: 'Dynamic Field. See Model Definitions'
66
+ }
67
+
68
+ if definition[0][:type] == 'array'
69
+ definition.each { |it| it[:type] = 'hash'}
70
+ documentation[:oneOf] = definition.map{ |it| generate_field_properties(it) }
71
+ { type: :array, items: documentation }
72
+ else
73
+ documentation[:oneOf] = definition.map{ |it| generate_field_properties(it) }
74
+ documentation
75
+ end
76
+ end
77
+
78
+ def generate_for_array(definition)
79
+ items = array_of_primitive_type?(definition) ?
80
+ SWAGGER_FIELD_TYPE_DEFINITIONS.fetch(definition.fetch(:type)) :
81
+ generate_documentation(definition.fetch(:keys))
82
+ items = @config.enable_nullable_validation ?
83
+ items.merge(@config.nullable_type => definition.fetch(@config.nullable_type, false)) :
84
+ items.merge(@config.nullable_type => true)
85
+ { type: :array, items: items }
86
+ end
87
+
88
+ def generate_for_hash(definition)
89
+ raise Errors::MissingHashSchemaError.new unless definition[:keys]
90
+ generate_documentation(definition.fetch(:keys))
91
+ end
92
+
93
+ def generate_for_primitive_type(definition)
94
+ documentation = SWAGGER_FIELD_TYPE_DEFINITIONS.fetch(definition.fetch(:type))
95
+ documentation = documentation.merge(enum: definition.fetch(:enum)) if definition[:enum] && @config.enable_enums
96
+ documentation = documentation.merge(description: definition.fetch(:description)) if definition[:description] &&
97
+ @config.enable_descriptions
98
+ documentation
99
+ end
100
+
101
+ def array_of_primitive_type?(definition)
102
+ definition[:array] && definition.fetch(:type) != 'array'
103
+ end
97
104
  end
98
105
  end
99
106
  end
@@ -6,7 +6,7 @@ module Dry
6
6
  "Could not generate documentation for field %{field_name}. The field is defined as hash,
7
7
  but the schema is not defined.
8
8
  Valid types are: %{valid_types}.
9
- The parser has generated the following definition for the field: %{field_name}: %{attributes_hash}
9
+ The parser has generated the following definition for the field: %{field_name}: %{definition}
10
10
  "
11
11
  end
12
12
  end
@@ -6,7 +6,7 @@ module Dry
6
6
  "Could not generate documentation for field %{field_name}. The field is missing a type.
7
7
  If the field you have defined is an array, you must specify the type of the elements in that array.
8
8
  Valid types are: %{valid_types}.
9
- The parser has generated the following definition for the field: %{field_name}: %{attributes_hash}.
9
+ The parser has generated the following definition for the field: %{field_name}: %{definition}.
10
10
  "
11
11
  end
12
12
  end
@@ -0,0 +1,15 @@
1
+ require 'dry/swagger'
2
+ require 'rails'
3
+
4
+ module Dry
5
+ module Swagger
6
+ class Railtie < Rails::Railtie
7
+ railtie_name :my_gem
8
+
9
+ rake_tasks do
10
+ path = File.expand_path(__dir__)
11
+ Dir.glob("#{path}/tasks/**/*.rake").each { |f| load f }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -119,10 +119,9 @@ module Dry
119
119
  if node[0][0].equal?(:constrained)
120
120
  opts[:nullable] = true
121
121
  visit(node[1], opts) # ignore NilClass constrained
122
- elsif node[0][0].equal?(:struct) && node[1][0].equal?(:struct)
122
+ elsif node[0][0].equal?(:struct) || node[0][0].equal?(:sum)
123
123
  opts[:oneOf] = true
124
- visit(node[0], opts)
125
- visit(node[1], opts)
124
+ node.each { |child| visit(child, opts) unless child.is_a?(Hash) }
126
125
  end
127
126
  end
128
127
 
@@ -0,0 +1,49 @@
1
+ require 'fileutils'
2
+
3
+ namespace 'dry-swagger' do
4
+ desc 'Create a configuration file for Struct and Contract'
5
+ task :create_configuration_file do
6
+ FileUtils.mkdir_p "#{ Dir.pwd }/config/initializers/"
7
+ File.open("#{ Dir.pwd }/config/initializers/dry-swagger.rb", "w") { |file|
8
+ file.puts 'Dry::Swagger::Config::StructConfiguration.configuration do |config|
9
+ config.enable_required_validation = true
10
+ config.enable_nullable_validation = true
11
+ config.enable_enums = true
12
+ config.enable_descriptions = true
13
+ config.nullable_type = :"x-nullable" # or :nullable
14
+ end
15
+
16
+ Dry::Swagger::Config::ContractConfiguration.configuration do |config|
17
+ config.enable_required_validation = true
18
+ config.enable_nullable_validation = true
19
+ config.enable_enums = true
20
+ config.enable_descriptions = true
21
+ config.nullable_type = :"x-nullable" # or :nullable
22
+ end'
23
+ }
24
+ end
25
+
26
+ desc 'Create a YAML file for Contract swagger field descriptions'
27
+ task :create_contract_descriptions_yaml do
28
+ FileUtils.mkdir_p "#{ Dir.pwd }/config/locales/"
29
+ File.open("#{ Dir.pwd }/config/locales/dry-swagger.yml", "w") { |file|
30
+ file.puts 'en:
31
+ contract:
32
+ descriptions:
33
+ eql?: "Must be equal to %{value}"
34
+ max_size?: "Maximum size: %{value}"
35
+ min_size?: "Minimum size: %{value}"
36
+ gteq?: "Greater than or equal to %{value}"
37
+ gt?: "Greater than %{value}"
38
+ lt?: "Lower than %{value}"
39
+ lteq?: "Lower than or equal to %{value}"
40
+ '
41
+ }
42
+ end
43
+
44
+ desc 'Creates configuration files'
45
+ task :install do
46
+ Rake::Task['dry-swagger:create_configuration_file'].execute
47
+ Rake::Task['dry-swagger:create_contract_descriptions_yaml'].execute
48
+ end
49
+ end
@@ -1,5 +1,5 @@
1
1
  module Dry
2
2
  module Swagger
3
- VERSION = "0.5.1"
3
+ VERSION = "0.6.2"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-swagger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jane-Terziev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-03 00:00:00.000000000 Z
11
+ date: 2021-08-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A parser which converts dry-validation or dry-struct into valid swagger
14
14
  documentation
@@ -39,7 +39,9 @@ files:
39
39
  - lib/dry/swagger/documentation_generator.rb
40
40
  - lib/dry/swagger/errors/missing_hash_schema_error.rb
41
41
  - lib/dry/swagger/errors/missing_type_error.rb
42
+ - lib/dry/swagger/railtie.rb
42
43
  - lib/dry/swagger/struct_parser.rb
44
+ - lib/dry/swagger/tasks/configuration_generator.rake
43
45
  - lib/dry/swagger/types.rb
44
46
  - lib/dry/swagger/version.rb
45
47
  homepage: https://github.com/Jane-Terziev/dry-swagger