apipie-rails 0.9.4 → 1.0.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 +4 -4
- data/.rubocop.yml +8 -14
- data/.rubocop_todo.yml +102 -213
- data/CHANGELOG.md +17 -6
- data/README.rst +12 -12
- data/app/controllers/apipie/apipies_controller.rb +4 -4
- data/lib/apipie/apipie_module.rb +4 -4
- data/lib/apipie/application.rb +70 -54
- data/lib/apipie/configuration.rb +19 -26
- data/lib/apipie/dsl_definition.rb +4 -5
- data/lib/apipie/extractor/collector.rb +2 -2
- data/lib/apipie/extractor.rb +1 -1
- data/lib/apipie/generator/config.rb +12 -0
- data/lib/apipie/generator/swagger/computed_interface_id.rb +23 -0
- data/lib/apipie/generator/swagger/config.rb +78 -0
- data/lib/apipie/generator/swagger/context.rb +12 -1
- data/lib/apipie/generator/swagger/method_description/api_decorator.rb +20 -0
- data/lib/apipie/generator/swagger/method_description/api_schema_service.rb +86 -0
- data/lib/apipie/generator/swagger/method_description/decorator.rb +22 -0
- data/lib/apipie/generator/swagger/method_description/parameters_service.rb +139 -0
- data/lib/apipie/generator/swagger/method_description/response_schema_service.rb +46 -0
- data/lib/apipie/generator/swagger/method_description/response_service.rb +58 -0
- data/lib/apipie/generator/swagger/method_description.rb +2 -0
- data/lib/apipie/generator/swagger/operation_id.rb +1 -1
- data/lib/apipie/generator/swagger/param_description/builder.rb +4 -4
- data/lib/apipie/generator/swagger/param_description/composite.rb +9 -1
- data/lib/apipie/generator/swagger/param_description/in.rb +1 -1
- data/lib/apipie/generator/swagger/param_description/path_params_composite.rb +61 -0
- data/lib/apipie/generator/swagger/param_description/referenced_composite.rb +36 -0
- data/lib/apipie/generator/swagger/param_description/type.rb +9 -2
- data/lib/apipie/generator/swagger/path_decorator.rb +36 -0
- data/lib/apipie/generator/swagger/referenced_definitions.rb +17 -0
- data/lib/apipie/generator/swagger/resource_description_collection.rb +30 -0
- data/lib/apipie/generator/swagger/resource_description_composite.rb +56 -0
- data/lib/apipie/generator/swagger/schema.rb +63 -0
- data/lib/apipie/generator/swagger/type_extractor.rb +0 -19
- data/lib/apipie/generator/swagger/warning.rb +3 -6
- data/lib/apipie/generator/swagger/warning_writer.rb +7 -1
- data/lib/apipie/method_description.rb +4 -2
- data/lib/apipie/param_description.rb +4 -2
- data/lib/apipie/resource_description.rb +1 -1
- data/lib/apipie/swagger_generator.rb +27 -551
- data/lib/apipie/validator.rb +7 -3
- data/lib/apipie/version.rb +1 -1
- data/lib/apipie-rails.rb +17 -0
- data/lib/tasks/apipie.rake +15 -10
- data/spec/controllers/api/v2/nested/resources_controller_spec.rb +2 -2
- data/spec/controllers/pets_controller_spec.rb +10 -16
- data/spec/controllers/users_controller_spec.rb +2 -2
- data/spec/dummy/app/controllers/pets_controller.rb +4 -4
- data/spec/dummy/app/controllers/pets_using_self_describing_classes_controller.rb +2 -2
- data/spec/dummy/app/controllers/twitter_example_controller.rb +2 -2
- data/spec/dummy/app/controllers/users_controller.rb +5 -5
- data/spec/lib/apipie/application_spec.rb +16 -7
- data/spec/lib/apipie/configuration_spec.rb +15 -0
- data/spec/lib/apipie/generator/swagger/config_spec.rb +19 -0
- data/spec/lib/apipie/generator/swagger/context_spec.rb +22 -2
- data/spec/lib/apipie/generator/swagger/method_description/api_schema_service_spec.rb +106 -0
- data/spec/lib/apipie/generator/swagger/method_description/response_schema_service_spec.rb +105 -0
- data/spec/lib/apipie/generator/swagger/param_description/builder_spec.rb +1 -1
- data/spec/lib/apipie/generator/swagger/param_description/composite_spec.rb +2 -2
- data/spec/lib/apipie/generator/swagger/param_description/type_spec.rb +7 -7
- data/spec/lib/apipie/generator/swagger/path_decorator_spec.rb +57 -0
- data/spec/lib/apipie/generator/swagger/referenced_definitions_spec.rb +35 -0
- data/spec/lib/apipie/generator/swagger/resource_description_composite_spec.rb +37 -0
- data/spec/lib/apipie/generator/swagger/resource_descriptions_collection_spec.rb +57 -0
- data/spec/lib/apipie/generator/swagger/schema_spec.rb +89 -0
- data/spec/lib/apipie/generator/swagger/type_extractor_spec.rb +0 -43
- data/spec/lib/apipie/generator/swagger/warning_spec.rb +1 -1
- data/spec/lib/apipie/generator/swagger/warning_writer_spec.rb +19 -7
- data/spec/lib/apipie/method_description_spec.rb +101 -66
- data/spec/lib/apipie/param_description_spec.rb +209 -49
- data/spec/lib/apipie/param_group_spec.rb +1 -0
- data/spec/lib/apipie/resource_description_spec.rb +1 -1
- data/spec/lib/apipie/swagger_generator_spec.rb +94 -0
- data/spec/lib/apipie/validator_spec.rb +47 -11
- data/spec/lib/swagger/rake_swagger_spec.rb +4 -4
- data/spec/lib/swagger/swagger_dsl_spec.rb +7 -7
- data/spec/lib/validators/array_validator_spec.rb +1 -1
- metadata +28 -2
@@ -0,0 +1,36 @@
|
|
1
|
+
class Apipie::Generator::Swagger::PathDecorator < SimpleDelegator
|
2
|
+
def param_names
|
3
|
+
@param_names ||= scan(/:(\w+)/).map { |ar| ar[0].to_sym }
|
4
|
+
end
|
5
|
+
|
6
|
+
# @param [Symbol] param_name
|
7
|
+
def param?(param_name)
|
8
|
+
param_names.include?(param_name)
|
9
|
+
end
|
10
|
+
|
11
|
+
# @param [String] controller_method
|
12
|
+
#
|
13
|
+
# @return [Apipie::Generator::Swagger::PathDecorator]
|
14
|
+
def swagger_path(controller_method = nil)
|
15
|
+
current_path = gsub(/:(\w+)/, '{\1}').gsub(%r{/$}, '')
|
16
|
+
|
17
|
+
unless current_path.starts_with?('/')
|
18
|
+
warn_for_missing_slash(controller_method) if controller_method.present?
|
19
|
+
|
20
|
+
current_path = "/#{current_path}"
|
21
|
+
end
|
22
|
+
|
23
|
+
current_path
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# @param [String] controller_method
|
29
|
+
def warn_for_missing_slash(controller_method)
|
30
|
+
Apipie::Generator::Swagger::Warning.for_code(
|
31
|
+
Apipie::Generator::Swagger::Warning::ADDED_MISSING_SLASH_CODE,
|
32
|
+
controller_method,
|
33
|
+
{ path: self }
|
34
|
+
).warn_through_writer
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Apipie::Generator::Swagger::ReferencedDefinitions
|
2
|
+
include Singleton
|
3
|
+
|
4
|
+
attr_reader :definitions
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@definitions = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def add!(param_type, schema)
|
11
|
+
@definitions[param_type] = schema
|
12
|
+
end
|
13
|
+
|
14
|
+
def added?(name)
|
15
|
+
@definitions.key?(name)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Apipie::Generator::Swagger::ResourceDescriptionsCollection
|
2
|
+
# @param [Hash{String->Apipie::ResourceDescription}] resource_descriptions
|
3
|
+
def initialize(resource_descriptions)
|
4
|
+
@resource_descriptions = resource_descriptions
|
5
|
+
end
|
6
|
+
|
7
|
+
# @return [Array<Apipie::ResourceDescription>]
|
8
|
+
def filter(version:, resource_id:, method_name: nil)
|
9
|
+
resources = []
|
10
|
+
|
11
|
+
# If resource_id is blank, take just resources which have some methods because
|
12
|
+
# we dont want to show eg ApplicationController as resource
|
13
|
+
# otherwise, take only the specified resource
|
14
|
+
@resource_descriptions[version].each do |resource_description_id, resource_description|
|
15
|
+
if (resource_id.blank? && resource_description._methods.present?) || resource_description_id == resource_id
|
16
|
+
resources << resource_description
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
if method_name.present?
|
21
|
+
resources = resources.select do |resource_description|
|
22
|
+
resource_description._methods.select do |method_description_name, _|
|
23
|
+
method_description_name == method_name
|
24
|
+
end.present?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
resources
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
class Apipie::Generator::Swagger::ResourceDescriptionComposite
|
2
|
+
# @param [Array<Apipie::ResourceDescription>] resource_descriptions
|
3
|
+
def initialize(resource_descriptions, language:)
|
4
|
+
@resource_descriptions = resource_descriptions
|
5
|
+
@language = language
|
6
|
+
end
|
7
|
+
|
8
|
+
# @return [Hash{Symbol->Array | Hash}]
|
9
|
+
def to_swagger
|
10
|
+
{
|
11
|
+
tags: tags,
|
12
|
+
paths: paths
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Array]
|
17
|
+
def tags
|
18
|
+
results = []
|
19
|
+
|
20
|
+
@resource_descriptions.each do |resource_description|
|
21
|
+
next unless resource_description._full_description
|
22
|
+
|
23
|
+
results << {
|
24
|
+
name: resource_description._id,
|
25
|
+
description: Apipie.app.translate(
|
26
|
+
resource_description._full_description,
|
27
|
+
@language
|
28
|
+
)
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
results
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Hash]
|
36
|
+
def paths
|
37
|
+
results = {}
|
38
|
+
|
39
|
+
@resource_descriptions.each do |resource_description|
|
40
|
+
resource_description._methods.each_value do |method_description|
|
41
|
+
next unless method_description.show
|
42
|
+
|
43
|
+
result = Apipie::Generator::Swagger::MethodDescription::ApiSchemaService
|
44
|
+
.new(
|
45
|
+
Apipie::Generator::Swagger::MethodDescription::Decorator.new(method_description),
|
46
|
+
language: @language
|
47
|
+
)
|
48
|
+
.call
|
49
|
+
|
50
|
+
results.deep_merge!(result)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
results
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class Apipie::Generator::Swagger::Schema
|
2
|
+
# @param [Array<Apipie::ResourceDescription>] resource_descriptions
|
3
|
+
def initialize(resource_descriptions, version:, language:, clear_warnings:)
|
4
|
+
@resource_descriptions = resource_descriptions
|
5
|
+
@language = language
|
6
|
+
@clear_warnings = clear_warnings
|
7
|
+
@swagger = {
|
8
|
+
swagger: '2.0',
|
9
|
+
info: {
|
10
|
+
title: Apipie.configuration.app_name.to_s,
|
11
|
+
description: "#{Apipie.app_info(version, @language)}#{Apipie.configuration.copyright}",
|
12
|
+
version: version.to_s,
|
13
|
+
'x-copyright': Apipie.configuration.copyright
|
14
|
+
},
|
15
|
+
basePath: Apipie.api_base_url(version),
|
16
|
+
consumes: [],
|
17
|
+
paths: {},
|
18
|
+
definitions: {},
|
19
|
+
schemes: Apipie.configuration.generator.swagger.schemes,
|
20
|
+
tags: [],
|
21
|
+
securityDefinitions: Apipie.configuration.generator.swagger.security_definitions,
|
22
|
+
security: Apipie.configuration.generator.swagger.global_security
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def generate
|
27
|
+
if Apipie.configuration.generator.swagger.api_host.present?
|
28
|
+
@swagger[:host] = Apipie.configuration.generator.swagger.api_host
|
29
|
+
end
|
30
|
+
|
31
|
+
if Apipie.configuration.generator.swagger.content_type_input == :json
|
32
|
+
@swagger[:consumes] = ['application/json']
|
33
|
+
@swagger[:info][:title] += ' (params in:body)'
|
34
|
+
else
|
35
|
+
@swagger[:consumes] = ['application/x-www-form-urlencoded', 'multipart/form-data']
|
36
|
+
@swagger[:info][:title] += ' (params in:formData)'
|
37
|
+
end
|
38
|
+
|
39
|
+
if @clear_warnings
|
40
|
+
Apipie::Generator::Swagger::WarningWriter.instance.clear!
|
41
|
+
end
|
42
|
+
|
43
|
+
@swagger.merge!(tags_and_paths)
|
44
|
+
|
45
|
+
if Apipie.configuration.generator.swagger.generate_x_computed_id_field?
|
46
|
+
@swagger[:info]['x-computed-id'] =
|
47
|
+
Apipie::Generator::Swagger::ComputedInterfaceId.instance.id
|
48
|
+
end
|
49
|
+
|
50
|
+
@swagger[:definitions] =
|
51
|
+
Apipie::Generator::Swagger::ReferencedDefinitions.instance.definitions
|
52
|
+
|
53
|
+
@swagger
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def tags_and_paths
|
59
|
+
Apipie::Generator::Swagger::ResourceDescriptionComposite
|
60
|
+
.new(@resource_descriptions, language: @language)
|
61
|
+
.to_swagger
|
62
|
+
end
|
63
|
+
end
|
@@ -25,21 +25,10 @@ class Apipie::Generator::Swagger::TypeExtractor
|
|
25
25
|
@validator = validator
|
26
26
|
end
|
27
27
|
|
28
|
-
# @param [Hash<Symbol, Apipie::Generator::Swagger::Warning>] warnings
|
29
|
-
def extract_with_warnings(warnings = {})
|
30
|
-
if boolean? && warnings[:boolean].present?
|
31
|
-
Apipie::Generator::Swagger::WarningWriter.instance.warn(warnings[:boolean])
|
32
|
-
end
|
33
|
-
|
34
|
-
extract
|
35
|
-
end
|
36
|
-
|
37
28
|
def extract
|
38
29
|
expected_type =
|
39
30
|
if string?
|
40
31
|
:string
|
41
|
-
elsif boolean?
|
42
|
-
:boolean
|
43
32
|
elsif enum?
|
44
33
|
:enum
|
45
34
|
else
|
@@ -59,12 +48,4 @@ class Apipie::Generator::Swagger::TypeExtractor
|
|
59
48
|
@validator.is_a?(Apipie::Validator::EnumValidator) ||
|
60
49
|
(@validator.respond_to?(:is_enum?) && @validator.is_enum?)
|
61
50
|
end
|
62
|
-
|
63
|
-
def boolean?
|
64
|
-
@_boolean ||= enum? && boolean_values?
|
65
|
-
end
|
66
|
-
|
67
|
-
def boolean_values?
|
68
|
-
@validator.values.to_set == Set.new([true, false])
|
69
|
-
end
|
70
51
|
end
|
@@ -7,7 +7,6 @@ class Apipie::Generator::Swagger::Warning
|
|
7
7
|
OPTIONAL_WITHOUT_DEFAULT_VALUE_CODE = 105
|
8
8
|
PARAM_IGNORED_IN_FORM_DATA_CODE = 106
|
9
9
|
PATH_PARAM_NOT_DESCRIBED_CODE = 107
|
10
|
-
INFERRING_BOOLEAN_CODE = 108
|
11
10
|
|
12
11
|
CODES = {
|
13
12
|
missing_method_summary: MISSING_METHOD_SUMMARY_CODE,
|
@@ -17,8 +16,7 @@ class Apipie::Generator::Swagger::Warning
|
|
17
16
|
optional_param_in_path: OPTIONAL_PARAM_IN_PATH_CODE,
|
18
17
|
optional_without_default_value: OPTIONAL_WITHOUT_DEFAULT_VALUE_CODE,
|
19
18
|
param_ignored_in_form_data: PARAM_IGNORED_IN_FORM_DATA_CODE,
|
20
|
-
path_param_not_described_code: PATH_PARAM_NOT_DESCRIBED_CODE
|
21
|
-
inferring_boolean: INFERRING_BOOLEAN_CODE
|
19
|
+
path_param_not_described_code: PATH_PARAM_NOT_DESCRIBED_CODE
|
22
20
|
}
|
23
21
|
|
24
22
|
MESSAGES = {
|
@@ -29,8 +27,7 @@ class Apipie::Generator::Swagger::Warning
|
|
29
27
|
OPTIONAL_PARAM_IN_PATH_CODE => "The parameter :%{parameter} is 'in-path'. Ignoring 'not required' in DSL",
|
30
28
|
OPTIONAL_WITHOUT_DEFAULT_VALUE_CODE => "The parameter :%{parameter} is optional but default value is not specified (use :default_value => ...)",
|
31
29
|
PARAM_IGNORED_IN_FORM_DATA_CODE => "Ignoring param :%{parameter} -- cannot include Hash without fields in a formData specification",
|
32
|
-
PATH_PARAM_NOT_DESCRIBED_CODE => "The parameter :%{name} appears in the path %{path} but is not described"
|
33
|
-
INFERRING_BOOLEAN_CODE => "The parameter [%{parameter}] is Enum with [true, false] values. Inferring 'boolean'"
|
30
|
+
PATH_PARAM_NOT_DESCRIBED_CODE => "The parameter :%{name} appears in the path %{path} but is not described"
|
34
31
|
}
|
35
32
|
|
36
33
|
attr_reader :code
|
@@ -46,7 +43,7 @@ class Apipie::Generator::Swagger::Warning
|
|
46
43
|
end
|
47
44
|
|
48
45
|
def warning_message
|
49
|
-
"WARNING (#{@code}): [#{@method_id}] -- #{@info_message}"
|
46
|
+
"WARNING (#{@code}): [#{@method_id}] -- #{@info_message}\n"
|
50
47
|
end
|
51
48
|
|
52
49
|
def warn
|
@@ -18,6 +18,12 @@ class Apipie::Generator::Swagger::WarningWriter
|
|
18
18
|
@issued_warnings.count > 0
|
19
19
|
end
|
20
20
|
|
21
|
+
def clear!
|
22
|
+
@issued_warnings = []
|
23
|
+
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
21
27
|
private
|
22
28
|
|
23
29
|
# @param [Apipie::Generator::Swagger::Warning] warning
|
@@ -43,6 +49,6 @@ class Apipie::Generator::Swagger::WarningWriter
|
|
43
49
|
|
44
50
|
# @return [FalseClass, TrueClass, Array]
|
45
51
|
def suppress_warnings_config
|
46
|
-
Apipie.configuration.
|
52
|
+
Apipie.configuration.generator.swagger.suppress_warnings
|
47
53
|
end
|
48
54
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
module Apipie
|
2
|
-
|
3
2
|
class MethodDescription
|
4
3
|
attr_reader :full_description, :method, :resource, :apis, :examples, :see, :formats, :headers, :show
|
5
4
|
attr_accessor :metadata
|
@@ -182,6 +181,10 @@ module Apipie
|
|
182
181
|
@from_concern
|
183
182
|
end
|
184
183
|
|
184
|
+
def method_name
|
185
|
+
@method
|
186
|
+
end
|
187
|
+
|
185
188
|
private
|
186
189
|
|
187
190
|
def merge_params(params, new_params)
|
@@ -224,5 +227,4 @@ module Apipie
|
|
224
227
|
example
|
225
228
|
end
|
226
229
|
end
|
227
|
-
|
228
230
|
end
|
@@ -57,6 +57,10 @@ module Apipie
|
|
57
57
|
@from_concern = @options[:param_group][:from_concern]
|
58
58
|
end
|
59
59
|
|
60
|
+
if validator.is_a?(Hash)
|
61
|
+
@options.merge!(validator.select{|k,v| k != :array_of })
|
62
|
+
end
|
63
|
+
|
60
64
|
@method_description = method_description
|
61
65
|
@name = concern_subst(name)
|
62
66
|
@as = options[:as] || @name
|
@@ -85,9 +89,7 @@ module Apipie
|
|
85
89
|
if validator
|
86
90
|
if (validator != Hash) && (validator.is_a? Hash) && (validator[:array_of])
|
87
91
|
@is_array = true
|
88
|
-
rest_of_options = validator
|
89
92
|
validator = validator[:array_of]
|
90
|
-
options.merge!(rest_of_options.select{|k,v| k != :array_of })
|
91
93
|
raise "an ':array_of =>' validator is allowed exclusively on response-only fields" unless @response_only
|
92
94
|
end
|
93
95
|
@validator = Validator::BaseValidator.find(self, validator, @options, block)
|
@@ -65,7 +65,7 @@ module Apipie
|
|
65
65
|
alias _name name
|
66
66
|
|
67
67
|
def add_method_description(method_description)
|
68
|
-
Apipie.debug "@resource_descriptions[#{self._version}][#{self.
|
68
|
+
Apipie.debug "@resource_descriptions[#{self._version}][#{self._id}]._methods[#{method_description.method}] = #{method_description}"
|
69
69
|
@_methods[method_description.method.to_sym] = method_description
|
70
70
|
end
|
71
71
|
|