swagger_autogenerate 1.2.4 → 1.2.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d62d2b3204e47e668408ea353aa7f5015a9f1a8f86e727e635b1030e999f587
4
- data.tar.gz: 7cbcbfc449684fe35db3c76c7c8bb0ae357ebabf8585ba7289c3b6d58abec9a9
3
+ metadata.gz: 711b43ae4aa65205938e96a052bcbc97afe0320ae62608c864b85ca7a5a8c5c1
4
+ data.tar.gz: 389a4adf130cb3c09bf1575ac5e1f2916dc38b47021ea5e7396b38bb482fa052
5
5
  SHA512:
6
- metadata.gz: f9dea5813fe7a651d4fa59d618b86a02a2e909a23bdcb8744aa56bd96ff667143482d52316b70f78868c2cbbf3de5e2e6104b9cdb8f13e00e6a2483f15ac2da7
7
- data.tar.gz: a7fa27d728d65a7e8d2fb58dcb052c81d1486a1d3c89b3326851797419cff037e28322eec8284a19f81be1c4121ed9dd33a83605a31ee1606bdccfa61b30c813
6
+ metadata.gz: d472c6a346336bd81902c6da48b1b1e814bcc0153f2a7bb71df92239aa85b3f1d1e70c307fa1872814e7657412f6234e0fd870c7196a36f3f12ff164dda9a535
7
+ data.tar.gz: 36dffa08dfcc34b94aee951b867e5ba383eb79f5327d53d0e3c403e29841cc27f772cc691ad526cc85ab4e7b38e67fff6fcf24319a701342536b20e8119c5b86
data/CHANGELOG.md CHANGED
@@ -17,5 +17,7 @@
17
17
  ## [1.2.2] - 2024-09-12
18
18
  ## [1.2.3] - 2024-09-12
19
19
  ## [1.2.4] - 2024-09-15
20
+ ## [1.2.5] - 2024-09-15
21
+ ## [1.2.6] - 2024-11-05
20
22
 
21
23
  - Initial release
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- swagger_autogenerate (1.2.4)
4
+ swagger_autogenerate (1.2.6)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -47,8 +47,8 @@ To configure the swagger_autogenerate gem in your Rails application, follow thes
47
47
  ```
48
48
  SwaggerAutogenerate.configure do |config|
49
49
  config.with_config = true
50
- config.with_example_description = true
51
50
  config.with_multiple_examples = true
51
+ action_for_old_examples = :append # :replace or :append
52
52
  config.with_response_description = true
53
53
  end
54
54
 
@@ -64,7 +64,7 @@ This file should contain the test scenarios for each action (e.g., index, show,
64
64
 
65
65
  3) Run the spec code using the rspec command and set the environment variable SWAGGER to the desired YAML file name. For example:
66
66
  ```
67
- SWAGGER_PATH='employee_apis.yaml' rspec spec/your_path/employees_controller_spec.rb
67
+ SWAGGER_GENERATE_PATH='employee_apis.yaml' rspec spec/your_path/employees_controller_spec.rb
68
68
  ```
69
69
  4) This command runs the spec file and instructs the swagger_autogenerate gem to generate Swagger YAML documentation and save it to the file named employee_apis.yaml.
70
70
  5) Once the command finishes executing, you will have the Swagger YAML documentation generated based on the test scenarios in the employees_controller_spec.rb file.
@@ -7,6 +7,7 @@ module SwaggerAutogenerate
7
7
  @with_multiple_examples = ::SwaggerAutogenerate.configuration.with_multiple_examples
8
8
  @with_rspec_examples = ::SwaggerAutogenerate.configuration.with_rspec_examples
9
9
  @with_response_description = ::SwaggerAutogenerate.configuration.with_response_description
10
+ @with_payload_properties = ::SwaggerAutogenerate.configuration.with_payload_properties
10
11
  @security = ::SwaggerAutogenerate.configuration.security
11
12
  @swagger_config = ::SwaggerAutogenerate.configuration.swagger_config
12
13
  @response_status = ::SwaggerAutogenerate.configuration.response_status
@@ -50,7 +51,7 @@ module SwaggerAutogenerate
50
51
 
51
52
  attr_reader :request, :response, :current_path, :yaml_file, :configuration,
52
53
  :with_config, :with_multiple_examples, :with_rspec_examples,
53
- :with_response_description, :security, :response_status, :swagger_config,
54
+ :with_response_description, :with_payload_properties, :security, :response_status, :swagger_config,
54
55
  :default_path, :action_for_old_examples
55
56
 
56
57
  # main methods
@@ -59,7 +60,10 @@ module SwaggerAutogenerate
59
60
  path = request.path
60
61
 
61
62
  request.path_parameters.except(:controller, :format, :action).each do |k, v|
62
- path = path.gsub!(v, "{#{k}}")
63
+ path_array = path.split('/')
64
+ index = path_array.rindex(v)
65
+ path_array[index] = "{#{k}}"
66
+ path.replace(path_array.join('/'))
63
67
  end
64
68
 
65
69
  @current_path = path
@@ -75,7 +79,7 @@ module SwaggerAutogenerate
75
79
  'requestBody' => request_body,
76
80
  'parameters' => parameters,
77
81
  'responses' => {},
78
- 'security' => security
82
+ 'security' => current_security
79
83
  }
80
84
  }
81
85
 
@@ -98,6 +102,7 @@ module SwaggerAutogenerate
98
102
 
99
103
  def create_file
100
104
  File.open(swagger_location, 'w') do |file|
105
+ return file.write(YAML.dump({ 'paths' => {} })) if paths.blank?
101
106
  data = with_config ? swagger_config : {}
102
107
  data['paths'] = paths
103
108
  organize_result(data['paths'])
@@ -108,18 +113,21 @@ module SwaggerAutogenerate
108
113
  current_example = old_examples[example_title]
109
114
  new_example(example_title, current_example, old_examples, data['paths'], true)
110
115
  # result
111
-
112
- result = add_quotes_to_dates(YAML.dump(data))
116
+ result = reformat_dates_in_hash(data)
117
+ result = convert_to_hash(result)
118
+ result = YAML.dump(result)
113
119
  file.write(result)
114
120
  end
115
121
  end
116
122
 
117
123
  def edit_file
118
- @yaml_file = YAML.load(
119
- File.read(swagger_location),
120
- aliases: true,
121
- permitted_classes: [Symbol, Date, ActiveSupport::HashWithIndifferentAccess]
122
- )
124
+ @yaml_file = \
125
+ YAML.safe_load(
126
+ File.read(swagger_location),
127
+ aliases: true,
128
+ permitted_classes: [Symbol, DateTime, Date, Time, ActiveSupport::HashWithIndifferentAccess],
129
+ permitted_symbols: []
130
+ )
123
131
 
124
132
  return create_file if yaml_file.nil? || yaml_file['paths'].nil?
125
133
 
@@ -129,7 +137,9 @@ module SwaggerAutogenerate
129
137
  organize_result(yaml_file['paths'])
130
138
  @yaml_file = convert_to_hash(yaml_file)
131
139
  File.open(swagger_location, 'w') do |file|
132
- result = add_quotes_to_dates(YAML.dump(yaml_file))
140
+ result = reformat_dates_in_hash(yaml_file)
141
+ result = convert_to_hash(result)
142
+ result = YAML.dump(result)
133
143
  file.write(result)
134
144
  end
135
145
  end
@@ -137,6 +147,7 @@ module SwaggerAutogenerate
137
147
  # Helpers
138
148
 
139
149
  def process_replacing_examples
150
+ create_file_if_not_exist
140
151
  $removed_examples ||= []
141
152
  if action_for_old_examples == :replace && !$removed_examples.include?({ @current_path => request.method.to_s.downcase })
142
153
  current_yaml_file = YAML.load(
@@ -145,10 +156,13 @@ module SwaggerAutogenerate
145
156
  permitted_classes: [Symbol, Date, ActiveSupport::HashWithIndifferentAccess]
146
157
  )
147
158
 
148
- current_yaml_file["paths"][@current_path][request.method.to_s.downcase] = {}
159
+ hash = { "paths" => { @current_path => { request.method.to_s.downcase => {} } } }
149
160
 
161
+ current_yaml_file&.merge!(hash)
150
162
  File.open(swagger_location, 'w') do |file|
151
- result = add_quotes_to_dates(YAML.dump(current_yaml_file))
163
+ result = reformat_dates_in_hash(current_yaml_file)
164
+ result = convert_to_hash(result)
165
+ result = YAML.dump(result)
152
166
  file.write(result)
153
167
  end
154
168
 
@@ -156,13 +170,23 @@ module SwaggerAutogenerate
156
170
  end
157
171
  end
158
172
 
159
- def add_quotes_to_dates(string)
160
- string = remove_quotes_in_dates(string)
161
- string.gsub(/\b\d{4}-\d{2}-\d{2}\b/, "'\\0'")
162
- end
163
-
164
- def remove_quotes_in_dates(string)
165
- string.gsub(/'(\d{4}-\d{2}-\d{2})'/, '\1')
173
+ def reformat_dates_in_hash(data)
174
+ case data
175
+ when Hash
176
+ data.each do |key, value|
177
+ data[key] = reformat_dates_in_hash(value)
178
+ end
179
+ when Array
180
+ data.map! { |element| reformat_dates_in_hash(element) }
181
+ when String
182
+ if is_valid_date?(data)
183
+ convert_to_date(data).to_s
184
+ else
185
+ data
186
+ end
187
+ else
188
+ data
189
+ end
166
190
  end
167
191
 
168
192
  def convert_to_hash(obj)
@@ -198,6 +222,15 @@ module SwaggerAutogenerate
198
222
  hash
199
223
  end
200
224
 
225
+ def schema_type(value)
226
+ return 'integer' if number?(value)
227
+ return 'boolean' if (value.try(:downcase) == 'true') || (value.try(:downcase) == 'false')
228
+ return 'string' if value.instance_of?(String) || value.instance_of?(Symbol)
229
+ return 'array' if value.instance_of?(Array)
230
+
231
+ 'object'
232
+ end
233
+
201
234
  def set_parameters(parameters, parameter, required: false)
202
235
  return if parameter.blank?
203
236
 
@@ -222,11 +255,41 @@ module SwaggerAutogenerate
222
255
  end
223
256
 
224
257
  def tags
225
- [ENV['tag'] || controller_name]
258
+ [yaml_file&.dig('paths', current_path, request.method.downcase, 'tags')&.last&.capitalize || ENV['tag'] || controller_name&.capitalize]
226
259
  end
227
260
 
228
261
  def summary
229
- URI.parse(request.path).path
262
+ yaml_file&.dig('paths', current_path, request.method.downcase, 'summary') || handel_summary(request.method.downcase, current_path)
263
+ end
264
+
265
+ def handel_summary(method, path)
266
+ path_segments = path.split('/')
267
+ resource = format_path_to_title(path)&.gsub(' ', ' ')
268
+ id_segment = path.include?('{')
269
+
270
+ case method.upcase
271
+ when 'GET'
272
+ id_segment ? "Get #{resource}" : "Get All #{resource&.pluralize}"
273
+ when 'POST'
274
+ "Create #{resource}"
275
+ when 'PUT'
276
+ "Update #{resource}"
277
+ when 'DELETE'
278
+ "Delete #{resource}"
279
+ else
280
+ ""
281
+ end
282
+ end
283
+
284
+ def format_path_to_title(path)
285
+ cleaned_path = path.sub(%r{^/v\d+/}, '')
286
+ cleaned_path.gsub!(/\{[^}]+\}/, '')
287
+ title = cleaned_path.split('/').map(&:capitalize).join(' ')
288
+ title
289
+ end
290
+
291
+ def current_security
292
+ yaml_file&.dig('paths', current_path, request.method.downcase, 'security') || security
230
293
  end
231
294
 
232
295
  def response_description
@@ -328,8 +391,12 @@ module SwaggerAutogenerate
328
391
  { 'type' => 'array', 'items' => { 'oneOf' => item_schemas.uniq } }
329
392
  end
330
393
  when String
331
- if is_valid_date?(json)
332
- { 'type' => 'Date', 'example' => json.to_date.to_s }
394
+ if integer?(json)
395
+ { 'type' => 'integer', 'example' => json.to_i }
396
+ elsif number?(json)
397
+ { 'type' => 'number', 'example' => json.to_f }
398
+ elsif is_valid_date?(json)
399
+ { 'type' => 'string', 'example' => json.to_date.to_s }
333
400
  else
334
401
  { 'type' => 'string', 'example' => json.to_s }
335
402
  end
@@ -340,7 +407,7 @@ module SwaggerAutogenerate
340
407
  when TrueClass, FalseClass
341
408
  { 'type' => 'boolean', 'example' => json }
342
409
  when Date, Time, DateTime
343
- { 'type' => 'Date', 'example' => json.to_date.to_s }
410
+ { 'type' => 'string', 'example' => json.to_date.to_s }
344
411
  else
345
412
  { 'type' => 'string', 'example' => json.to_s }
346
413
  end
@@ -403,13 +470,10 @@ module SwaggerAutogenerate
403
470
  false
404
471
  end
405
472
 
406
- def schema_type(value)
407
- return 'integer' if number?(value)
408
- return 'boolean' if (value.try(:downcase) == 'true') || (value.try(:downcase) == 'false')
409
- return 'string' if value.instance_of?(String) || value.instance_of?(Symbol)
410
- return 'array' if value.instance_of?(Array)
411
-
412
- 'object'
473
+ def integer?(value)
474
+ true if Integer(value)
475
+ rescue StandardError
476
+ false
413
477
  end
414
478
 
415
479
  def example(value)
@@ -428,8 +492,9 @@ module SwaggerAutogenerate
428
492
  end
429
493
 
430
494
  def convert_to_date(string)
431
- datetime = DateTime.strptime(string)
432
- datetime.strftime('%Y-%m-%d')
495
+ datetime = Date.strptime(string)
496
+ return Date.parse(string).strftime('%Y/%m/%d') if datetime.year == 1
497
+ datetime.strftime('%Y/%m/%d')
433
498
  rescue ArgumentError
434
499
  string
435
500
  end
@@ -474,13 +539,13 @@ module SwaggerAutogenerate
474
539
  if ENV[generate_swagger_environment_variable].present?
475
540
  directory_path = Rails.root.join(default_path).to_s
476
541
  FileUtils.mkdir_p(directory_path) unless File.directory?(directory_path)
477
- @swagger_location = "#{directory_path}/#{tags.first}.yaml"
542
+ @swagger_location = "#{directory_path}/#{snake_case(tags&.first)}.yaml"
478
543
  elsif ENV[swagger_path_environment_variable].include?('.yaml') || ENV[swagger_path_environment_variable].include?('.yml')
479
544
  @swagger_location = Rails.root.join(ENV.fetch(swagger_path_environment_variable, nil).to_s).to_s
480
545
  else
481
546
  directory_path = Rails.root.join(ENV.fetch(swagger_path_environment_variable, nil).to_s).to_s
482
547
  FileUtils.mkdir_p(directory_path) unless File.directory?(directory_path)
483
- @swagger_location = "#{directory_path}/#{tags.first}.yaml"
548
+ @swagger_location = "#{directory_path}/#{snake_case(tags&.first)}.yaml"
484
549
  end
485
550
  end
486
551
 
@@ -539,14 +604,17 @@ module SwaggerAutogenerate
539
604
  end
540
605
 
541
606
  def new_example(example_title, current_example, old_examples, all_paths = yaml_file['paths'], with_schema_properties = false)
542
- if !old_examples.value?(current_example)
543
- last_example = handel_name_last_example(old_examples)
544
- last_example ||= example_title
545
- last_example = example_title unless with_multiple_examples
546
- all_paths[current_path][request.method.downcase]['responses'][response.status.to_s]['content']['application/json']['examples'][last_example] = current_example
547
- add_properties_to_schema(last_example, all_paths[current_path])
548
- elsif with_schema_properties
549
- add_properties_to_schema(full_rspec_description.present? ? full_rspec_description : 'example-0', all_paths[current_path])
607
+ if with_multiple_examples || old_examples&.keys&.count.to_i <= 1
608
+ if !old_examples&.value?(current_example)
609
+ last_example = handel_name_last_example(old_examples)
610
+ last_example ||= example_title
611
+ last_example = example_title
612
+ hash = { 'examples' => { last_example => current_example } }
613
+ all_paths[current_path][request.method.downcase]['responses'][response.status.to_s]['content']['application/json'].deep_merge!(hash)
614
+ add_properties_to_schema(last_example, all_paths[current_path])
615
+ elsif with_schema_properties
616
+ add_properties_to_schema(full_rspec_description.present? ? full_rspec_description : 'example-0', all_paths[current_path])
617
+ end
550
618
  end
551
619
 
552
620
  true
@@ -554,32 +622,34 @@ module SwaggerAutogenerate
554
622
 
555
623
  def handel_name_last_example(old_examples)
556
624
  last_example = full_rspec_description || old_examples.keys.last
557
- if old_examples.keys.include?(last_example)
625
+ if old_examples&.keys&.include?(last_example)
558
626
  last_example += '-1'
559
627
  json_example_plus_one(last_example)
560
628
  end
561
629
  end
562
630
 
563
631
  def add_properties_to_schema(last_example, main_path = yaml_file['paths'][current_path])
564
- parameters = {}
565
- parameters.merge!(request_parameters.values.first, query_parameters.values.first, path_parameters.values.first)
566
- hash = {
567
- last_example => build_properties(parameters.as_json)
568
- }
632
+ if with_payload_properties
633
+ parameters = {}
634
+ parameters.merge!(request_parameters.values.first, query_parameters.values.first, path_parameters.values.first)
635
+ hash = {
636
+ last_example => build_properties(parameters.as_json)
637
+ }
569
638
 
570
- main_path[request.method.downcase]['responses'][response.status.to_s].deep_merge!(
571
- {
572
- 'content' => {
573
- 'application/json' => {
574
- 'schema' => {
575
- 'description' => 'These are the payloads for each example',
576
- 'type' => 'object',
577
- 'properties' => hash
639
+ main_path[request.method.downcase]['responses'][response.status.to_s].deep_merge!(
640
+ {
641
+ 'content' => {
642
+ 'application/json' => {
643
+ 'schema' => {
644
+ 'description' => 'These are the payloads for each example',
645
+ 'type' => 'object',
646
+ 'properties' => hash
647
+ }
578
648
  }
579
649
  }
580
650
  }
581
- }
582
- )
651
+ )
652
+ end
583
653
  end
584
654
 
585
655
  def apply_yaml_file_changes
@@ -595,16 +665,19 @@ module SwaggerAutogenerate
595
665
  # checks
596
666
 
597
667
  def organize_result(current_paths)
598
- new_hash = {
599
- 'tags' => tags,
600
- 'summary' => summary
601
- }
602
- new_hash['parameters'] = current_paths[current_path][request.method.downcase]['parameters'] if current_paths[current_path][request.method.downcase]['parameters']
603
- new_hash['requestBody'] = current_paths[current_path][request.method.downcase]['requestBody'] if current_paths[current_path][request.method.downcase]['requestBody']
604
- new_hash['responses'] = current_paths[current_path][request.method.downcase]['responses']
605
- new_hash['security'] = security
668
+ if current_paths.dig(current_path, request.method.downcase).present?
669
+ new_hash = {
670
+ 'tags' => tags,
671
+ 'summary' => summary
672
+ }
673
+
674
+ new_hash['parameters'] = current_paths[current_path][request.method.downcase]['parameters'] if current_paths.dig(current_path, request.method.downcase, 'parameters')
675
+ new_hash['requestBody'] = current_paths[current_path][request.method.downcase]['requestBody'] if current_paths.dig(current_path, request.method.downcase, 'requestBody')
676
+ new_hash['responses'] = current_paths[current_path][request.method.downcase]['responses']
677
+ new_hash['security'] = current_security
606
678
 
607
- current_paths[current_path][request.method.downcase] = new_hash
679
+ current_paths[current_path][request.method.downcase] = new_hash
680
+ end
608
681
  end
609
682
 
610
683
  def check_path
@@ -637,13 +710,13 @@ module SwaggerAutogenerate
637
710
  end
638
711
 
639
712
  def check_parameters
640
- if old_paths[current_path][request.method.downcase]['parameters'].blank?
641
- yaml_file['paths'][current_path][request.method.downcase]['parameters'] = paths[current_path][request.method.downcase]['parameters']
713
+ if old_paths[current_path][request.method.downcase]['parameters'].blank? || old_paths.dig(current_path, request.method.downcase, 'responses')&.key?('200')
714
+ yaml_file['paths'][current_path][request.method.downcase]['parameters'] = paths.dig(current_path, request.method.downcase, 'parameters') if paths.dig(current_path, request.method.downcase, 'parameters').present?
642
715
  end
643
716
  end
644
717
 
645
718
  def check_parameter
646
- param_names = paths[current_path][request.method.downcase]['parameters'].pluck('name') - yaml_file['paths'][current_path][request.method.downcase]['parameters'].pluck('name')
719
+ param_names = Array.wrap(paths[current_path][request.method.downcase]['parameters']&.pluck('name')) - Array.wrap(yaml_file['paths'][current_path][request.method.downcase]['parameters']&.pluck('name'))
647
720
  param_names.each do |param_name|
648
721
  param = paths[current_path][request.method.downcase]['parameters'].find { |parameter| parameter['name'] == param_name }
649
722
  yaml_file['paths'][current_path][request.method.downcase]['parameters'].push(param)
@@ -681,6 +754,20 @@ module SwaggerAutogenerate
681
754
  with_rspec_examples ? SwaggerAutogenerate::SwaggerTrace.rspec_description : nil
682
755
  end
683
756
 
757
+ def create_file_if_not_exist
758
+ create_file unless File.exist?(swagger_location)
759
+ end
760
+
761
+ def snake_case(text)
762
+ return text&.downcase if text&.match?(/\A[A-Z]+\z/)
763
+
764
+ text
765
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
766
+ .gsub(/([a-z])([A-Z])/, '\1_\2')
767
+ .downcase
768
+ .tr(' ', '_')
769
+ end
770
+
684
771
  class << self
685
772
  attr_accessor :rspec_description
686
773
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SwaggerAutogenerate
4
- VERSION = "1.2.4"
4
+ VERSION = "1.2.6"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: swagger_autogenerate
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: 1.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - MohammedBuraiah
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-09-15 00:00:00.000000000 Z
11
+ date: 2024-11-05 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Generating Swagger YAML Automatically Based on Existing Test Cases in
14
14
  Ruby on Rails
@@ -56,7 +56,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
56
56
  - !ruby/object:Gem::Version
57
57
  version: '0'
58
58
  requirements: []
59
- rubygems_version: 3.4.19
59
+ rubygems_version: 3.1.6
60
60
  signing_key:
61
61
  specification_version: 4
62
62
  summary: Automating Swagger YAML generation in Ruby on Rails offers a range of benefits