apipie-rails 0.9.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -14
  3. data/.rubocop_todo.yml +102 -213
  4. data/CHANGELOG.md +17 -6
  5. data/README.rst +12 -12
  6. data/app/controllers/apipie/apipies_controller.rb +4 -4
  7. data/lib/apipie/apipie_module.rb +4 -4
  8. data/lib/apipie/application.rb +70 -54
  9. data/lib/apipie/configuration.rb +19 -26
  10. data/lib/apipie/dsl_definition.rb +4 -5
  11. data/lib/apipie/extractor/collector.rb +2 -2
  12. data/lib/apipie/extractor.rb +1 -1
  13. data/lib/apipie/generator/config.rb +12 -0
  14. data/lib/apipie/generator/swagger/computed_interface_id.rb +23 -0
  15. data/lib/apipie/generator/swagger/config.rb +78 -0
  16. data/lib/apipie/generator/swagger/context.rb +12 -1
  17. data/lib/apipie/generator/swagger/method_description/api_decorator.rb +20 -0
  18. data/lib/apipie/generator/swagger/method_description/api_schema_service.rb +86 -0
  19. data/lib/apipie/generator/swagger/method_description/decorator.rb +22 -0
  20. data/lib/apipie/generator/swagger/method_description/parameters_service.rb +139 -0
  21. data/lib/apipie/generator/swagger/method_description/response_schema_service.rb +46 -0
  22. data/lib/apipie/generator/swagger/method_description/response_service.rb +58 -0
  23. data/lib/apipie/generator/swagger/method_description.rb +2 -0
  24. data/lib/apipie/generator/swagger/operation_id.rb +1 -1
  25. data/lib/apipie/generator/swagger/param_description/builder.rb +4 -4
  26. data/lib/apipie/generator/swagger/param_description/composite.rb +9 -1
  27. data/lib/apipie/generator/swagger/param_description/in.rb +1 -1
  28. data/lib/apipie/generator/swagger/param_description/path_params_composite.rb +61 -0
  29. data/lib/apipie/generator/swagger/param_description/referenced_composite.rb +36 -0
  30. data/lib/apipie/generator/swagger/param_description/type.rb +9 -2
  31. data/lib/apipie/generator/swagger/path_decorator.rb +36 -0
  32. data/lib/apipie/generator/swagger/referenced_definitions.rb +17 -0
  33. data/lib/apipie/generator/swagger/resource_description_collection.rb +30 -0
  34. data/lib/apipie/generator/swagger/resource_description_composite.rb +56 -0
  35. data/lib/apipie/generator/swagger/schema.rb +63 -0
  36. data/lib/apipie/generator/swagger/type_extractor.rb +0 -19
  37. data/lib/apipie/generator/swagger/warning.rb +3 -6
  38. data/lib/apipie/generator/swagger/warning_writer.rb +7 -1
  39. data/lib/apipie/method_description.rb +4 -2
  40. data/lib/apipie/param_description.rb +4 -2
  41. data/lib/apipie/resource_description.rb +1 -1
  42. data/lib/apipie/swagger_generator.rb +27 -551
  43. data/lib/apipie/validator.rb +7 -3
  44. data/lib/apipie/version.rb +1 -1
  45. data/lib/apipie-rails.rb +17 -0
  46. data/lib/tasks/apipie.rake +15 -10
  47. data/spec/controllers/api/v2/nested/resources_controller_spec.rb +2 -2
  48. data/spec/controllers/pets_controller_spec.rb +10 -16
  49. data/spec/controllers/users_controller_spec.rb +2 -2
  50. data/spec/dummy/app/controllers/pets_controller.rb +4 -4
  51. data/spec/dummy/app/controllers/pets_using_self_describing_classes_controller.rb +2 -2
  52. data/spec/dummy/app/controllers/twitter_example_controller.rb +2 -2
  53. data/spec/dummy/app/controllers/users_controller.rb +5 -5
  54. data/spec/lib/apipie/application_spec.rb +16 -7
  55. data/spec/lib/apipie/configuration_spec.rb +15 -0
  56. data/spec/lib/apipie/generator/swagger/config_spec.rb +19 -0
  57. data/spec/lib/apipie/generator/swagger/context_spec.rb +22 -2
  58. data/spec/lib/apipie/generator/swagger/method_description/api_schema_service_spec.rb +106 -0
  59. data/spec/lib/apipie/generator/swagger/method_description/response_schema_service_spec.rb +105 -0
  60. data/spec/lib/apipie/generator/swagger/param_description/builder_spec.rb +1 -1
  61. data/spec/lib/apipie/generator/swagger/param_description/composite_spec.rb +2 -2
  62. data/spec/lib/apipie/generator/swagger/param_description/type_spec.rb +7 -7
  63. data/spec/lib/apipie/generator/swagger/path_decorator_spec.rb +57 -0
  64. data/spec/lib/apipie/generator/swagger/referenced_definitions_spec.rb +35 -0
  65. data/spec/lib/apipie/generator/swagger/resource_description_composite_spec.rb +37 -0
  66. data/spec/lib/apipie/generator/swagger/resource_descriptions_collection_spec.rb +57 -0
  67. data/spec/lib/apipie/generator/swagger/schema_spec.rb +89 -0
  68. data/spec/lib/apipie/generator/swagger/type_extractor_spec.rb +0 -43
  69. data/spec/lib/apipie/generator/swagger/warning_spec.rb +1 -1
  70. data/spec/lib/apipie/generator/swagger/warning_writer_spec.rb +19 -7
  71. data/spec/lib/apipie/method_description_spec.rb +101 -66
  72. data/spec/lib/apipie/param_description_spec.rb +209 -49
  73. data/spec/lib/apipie/param_group_spec.rb +1 -0
  74. data/spec/lib/apipie/resource_description_spec.rb +1 -1
  75. data/spec/lib/apipie/swagger_generator_spec.rb +94 -0
  76. data/spec/lib/apipie/validator_spec.rb +47 -11
  77. data/spec/lib/swagger/rake_swagger_spec.rb +4 -4
  78. data/spec/lib/swagger/swagger_dsl_spec.rb +7 -7
  79. data/spec/lib/validators/array_validator_spec.rb +1 -1
  80. 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.swagger_suppress_warnings
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._name}]._methods[#{method_description.method}] = #{method_description}"
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