apipierails3 0.0.1
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 +17 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.travis.yml +27 -0
- data/APACHE-LICENSE-2.0 +202 -0
- data/CHANGELOG.md +469 -0
- data/Gemfile +1 -0
- data/Gemfile.rails32 +6 -0
- data/Gemfile.rails41 +6 -0
- data/Gemfile.rails42 +11 -0
- data/Gemfile.rails50 +6 -0
- data/Gemfile.rails51 +7 -0
- data/MIT-LICENSE +20 -0
- data/NOTICE +4 -0
- data/PROPOSAL_FOR_RESPONSE_DESCRIPTIONS.md +244 -0
- data/README.rst +1874 -0
- data/Rakefile +13 -0
- data/apipierails3.gemspec +27 -0
- data/app/controllers/apipie/apipies_controller.rb +199 -0
- data/app/helpers/apipie_helper.rb +10 -0
- data/app/public/apipie/javascripts/apipie.js +6 -0
- data/app/public/apipie/javascripts/bundled/bootstrap-collapse.js +138 -0
- data/app/public/apipie/javascripts/bundled/bootstrap.js +1726 -0
- data/app/public/apipie/javascripts/bundled/jquery.js +5 -0
- data/app/public/apipie/javascripts/bundled/prettify.js +28 -0
- data/app/public/apipie/stylesheets/application.css +7 -0
- data/app/public/apipie/stylesheets/bundled/bootstrap-responsive.min.css +12 -0
- data/app/public/apipie/stylesheets/bundled/bootstrap.min.css +689 -0
- data/app/public/apipie/stylesheets/bundled/prettify.css +30 -0
- data/app/views/apipie/apipies/_disqus.html.erb +13 -0
- data/app/views/apipie/apipies/_errors.html.erb +23 -0
- data/app/views/apipie/apipies/_headers.html.erb +26 -0
- data/app/views/apipie/apipies/_languages.erb +6 -0
- data/app/views/apipie/apipies/_metadata.erb +1 -0
- data/app/views/apipie/apipies/_method_detail.erb +61 -0
- data/app/views/apipie/apipies/_params.html.erb +42 -0
- data/app/views/apipie/apipies/_params_plain.html.erb +20 -0
- data/app/views/apipie/apipies/apipie_404.html.erb +17 -0
- data/app/views/apipie/apipies/apipie_checksum.json.erb +1 -0
- data/app/views/apipie/apipies/getting_started.html.erb +6 -0
- data/app/views/apipie/apipies/index.html.erb +56 -0
- data/app/views/apipie/apipies/method.html.erb +41 -0
- data/app/views/apipie/apipies/plain.html.erb +77 -0
- data/app/views/apipie/apipies/resource.html.erb +80 -0
- data/app/views/apipie/apipies/static.html.erb +103 -0
- data/app/views/layouts/apipie/apipie.html.erb +27 -0
- data/config/locales/de.yml +28 -0
- data/config/locales/en.yml +32 -0
- data/config/locales/es.yml +28 -0
- data/config/locales/fr.yml +31 -0
- data/config/locales/it.yml +31 -0
- data/config/locales/ja.yml +31 -0
- data/config/locales/pl.yml +28 -0
- data/config/locales/pt-BR.yml +28 -0
- data/config/locales/ru.yml +28 -0
- data/config/locales/tr.yml +28 -0
- data/config/locales/zh-CN.yml +28 -0
- data/config/locales/zh-TW.yml +28 -0
- data/images/screenshot-1.png +0 -0
- data/images/screenshot-2.png +0 -0
- data/lib/apipie/apipie_module.rb +83 -0
- data/lib/apipie/application.rb +462 -0
- data/lib/apipie/configuration.rb +186 -0
- data/lib/apipie/dsl_definition.rb +607 -0
- data/lib/apipie/error_description.rb +44 -0
- data/lib/apipie/errors.rb +86 -0
- data/lib/apipie/extractor.rb +177 -0
- data/lib/apipie/extractor/collector.rb +117 -0
- data/lib/apipie/extractor/recorder.rb +166 -0
- data/lib/apipie/extractor/writer.rb +454 -0
- data/lib/apipie/helpers.rb +73 -0
- data/lib/apipie/markup.rb +48 -0
- data/lib/apipie/method_description.rb +273 -0
- data/lib/apipie/middleware/checksum_in_headers.rb +35 -0
- data/lib/apipie/param_description.rb +280 -0
- data/lib/apipie/railtie.rb +9 -0
- data/lib/apipie/resource_description.rb +124 -0
- data/lib/apipie/response_description.rb +131 -0
- data/lib/apipie/response_description_adapter.rb +200 -0
- data/lib/apipie/routes_formatter.rb +33 -0
- data/lib/apipie/routing.rb +16 -0
- data/lib/apipie/rspec/response_validation_helper.rb +192 -0
- data/lib/apipie/see_description.rb +39 -0
- data/lib/apipie/static_dispatcher.rb +69 -0
- data/lib/apipie/swagger_generator.rb +707 -0
- data/lib/apipie/tag_list_description.rb +11 -0
- data/lib/apipie/validator.rb +526 -0
- data/lib/apipie/version.rb +3 -0
- data/lib/apipierails3.rb +25 -0
- data/lib/generators/apipie/install/README +6 -0
- data/lib/generators/apipie/install/install_generator.rb +25 -0
- data/lib/generators/apipie/install/templates/initializer.rb.erb +7 -0
- data/lib/generators/apipie/views_generator.rb +11 -0
- data/lib/tasks/apipie.rake +345 -0
- data/rel-eng/packages/.readme +3 -0
- data/rel-eng/packages/rubygem-apipie-rails +1 -0
- data/rel-eng/tito.props +5 -0
- data/spec/controllers/api/v1/architectures_controller_spec.rb +29 -0
- data/spec/controllers/api/v2/architectures_controller_spec.rb +12 -0
- data/spec/controllers/api/v2/nested/resources_controller_spec.rb +11 -0
- data/spec/controllers/apipies_controller_spec.rb +273 -0
- data/spec/controllers/concerns_controller_spec.rb +42 -0
- data/spec/controllers/extended_controller_spec.rb +11 -0
- data/spec/controllers/users_controller_spec.rb +740 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/controllers/api/base_controller.rb +4 -0
- data/spec/dummy/app/controllers/api/v1/architectures_controller.rb +43 -0
- data/spec/dummy/app/controllers/api/v1/base_controller.rb +11 -0
- data/spec/dummy/app/controllers/api/v2/architectures_controller.rb +30 -0
- data/spec/dummy/app/controllers/api/v2/base_controller.rb +11 -0
- data/spec/dummy/app/controllers/api/v2/nested/architectures_controller.rb +32 -0
- data/spec/dummy/app/controllers/api/v2/nested/resources_controller.rb +33 -0
- data/spec/dummy/app/controllers/application_controller.rb +18 -0
- data/spec/dummy/app/controllers/concerns/extending_concern.rb +11 -0
- data/spec/dummy/app/controllers/concerns/sample_controller.rb +41 -0
- data/spec/dummy/app/controllers/concerns_controller.rb +8 -0
- data/spec/dummy/app/controllers/extended_controller.rb +14 -0
- data/spec/dummy/app/controllers/files_controller.rb +5 -0
- data/spec/dummy/app/controllers/overridden_concerns_controller.rb +31 -0
- data/spec/dummy/app/controllers/pets_controller.rb +408 -0
- data/spec/dummy/app/controllers/pets_using_auto_views_controller.rb +73 -0
- data/spec/dummy/app/controllers/pets_using_self_describing_classes_controller.rb +95 -0
- data/spec/dummy/app/controllers/tagged_cats_controller.rb +32 -0
- data/spec/dummy/app/controllers/tagged_dogs_controller.rb +15 -0
- data/spec/dummy/app/controllers/twitter_example_controller.rb +307 -0
- data/spec/dummy/app/controllers/users_controller.rb +297 -0
- data/spec/dummy/app/views/layouts/application.html.erb +21 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +49 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +21 -0
- data/spec/dummy/config/environment.rb +8 -0
- data/spec/dummy/config/environments/development.rb +28 -0
- data/spec/dummy/config/environments/production.rb +52 -0
- data/spec/dummy/config/environments/test.rb +38 -0
- data/spec/dummy/config/initializers/apipie.rb +110 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +8 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +51 -0
- data/spec/dummy/db/.gitkeep +0 -0
- data/spec/dummy/doc/apipie_examples.json +1 -0
- data/spec/dummy/doc/users/desc_from_file.md +1 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/lib/application_spec.rb +49 -0
- data/spec/lib/extractor/extractor_spec.rb +9 -0
- data/spec/lib/extractor/middleware_spec.rb +44 -0
- data/spec/lib/extractor/writer_spec.rb +110 -0
- data/spec/lib/file_handler_spec.rb +18 -0
- data/spec/lib/method_description_spec.rb +98 -0
- data/spec/lib/param_description_spec.rb +345 -0
- data/spec/lib/param_group_spec.rb +60 -0
- data/spec/lib/rake_spec.rb +71 -0
- data/spec/lib/resource_description_spec.rb +48 -0
- data/spec/lib/swagger/openapi_2_0_schema.json +1607 -0
- data/spec/lib/swagger/rake_swagger_spec.rb +139 -0
- data/spec/lib/swagger/response_validation_spec.rb +104 -0
- data/spec/lib/swagger/swagger_dsl_spec.rb +658 -0
- data/spec/lib/validator_spec.rb +113 -0
- data/spec/lib/validators/array_validator_spec.rb +85 -0
- data/spec/spec_helper.rb +109 -0
- data/spec/support/rake.rb +21 -0
- metadata +415 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
module Apipie
|
|
2
|
+
|
|
3
|
+
# Resource description
|
|
4
|
+
#
|
|
5
|
+
# version - api version (1)
|
|
6
|
+
# description
|
|
7
|
+
# path - relative path (/api/articles)
|
|
8
|
+
# methods - array of keys to Apipie.method_descriptions (array of Apipie::MethodDescription)
|
|
9
|
+
# name - human readable alias of resource (Articles)
|
|
10
|
+
# id - resouce name
|
|
11
|
+
# formats - acceptable request/response format types
|
|
12
|
+
# headers - array of headers
|
|
13
|
+
# deprecated - boolean indicating if resource is deprecated
|
|
14
|
+
class ResourceDescription
|
|
15
|
+
|
|
16
|
+
attr_reader :controller, :_short_description, :_full_description, :_methods, :_id,
|
|
17
|
+
:_path, :_name, :_params_args, :_returns_args, :_tag_list_arg, :_errors_args,
|
|
18
|
+
:_formats, :_parent, :_metadata, :_headers, :_deprecated
|
|
19
|
+
|
|
20
|
+
def initialize(controller, resource_name, dsl_data = nil, version = nil, &block)
|
|
21
|
+
|
|
22
|
+
@_methods = ActiveSupport::OrderedHash.new
|
|
23
|
+
@_params_args = []
|
|
24
|
+
@_errors_args = []
|
|
25
|
+
@_returns_args = []
|
|
26
|
+
|
|
27
|
+
@controller = controller
|
|
28
|
+
@_id = resource_name
|
|
29
|
+
@_version = version || Apipie.configuration.default_version
|
|
30
|
+
@_name = @_id.humanize
|
|
31
|
+
@_parent = Apipie.get_resource_description(controller.superclass, version)
|
|
32
|
+
|
|
33
|
+
update_from_dsl_data(dsl_data) if dsl_data
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def update_from_dsl_data(dsl_data)
|
|
37
|
+
@_name = dsl_data[:resource_name] if dsl_data[:resource_name]
|
|
38
|
+
@_full_description = Apipie.markup_to_html(dsl_data[:description])
|
|
39
|
+
@_short_description = dsl_data[:short_description]
|
|
40
|
+
@_path = dsl_data[:path] || ""
|
|
41
|
+
@_formats = dsl_data[:formats]
|
|
42
|
+
@_errors_args = dsl_data[:errors]
|
|
43
|
+
@_params_args = dsl_data[:params]
|
|
44
|
+
@_returns_args = dsl_data[:returns]
|
|
45
|
+
@_tag_list_arg = dsl_data[:tag_list]
|
|
46
|
+
@_metadata = dsl_data[:meta]
|
|
47
|
+
@_api_base_url = dsl_data[:api_base_url]
|
|
48
|
+
@_headers = dsl_data[:headers]
|
|
49
|
+
@_deprecated = dsl_data[:deprecated] || false
|
|
50
|
+
|
|
51
|
+
if dsl_data[:app_info]
|
|
52
|
+
Apipie.configuration.app_info[_version] = dsl_data[:app_info]
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def _version
|
|
57
|
+
@_version || @_parent.try(:_version) || Apipie.configuration.default_version
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def _api_base_url
|
|
61
|
+
@_api_base_url || @_parent.try(:_api_base_url) || Apipie.api_base_url(_version)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def add_method_description(method_description)
|
|
65
|
+
Apipie.debug "@resource_descriptions[#{self._version}][#{self._name}]._methods[#{method_description.method}] = #{method_description}"
|
|
66
|
+
@_methods[method_description.method.to_sym] = method_description
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def method_description(method_name)
|
|
70
|
+
@_methods[method_name.to_sym]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def remove_method_description(method_name)
|
|
74
|
+
if @_methods.has_key?(method_name)
|
|
75
|
+
@_methods.delete(method_name)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def method_descriptions
|
|
80
|
+
@_methods.values
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def doc_url
|
|
84
|
+
crumbs = []
|
|
85
|
+
crumbs << _version if Apipie.configuration.version_in_url
|
|
86
|
+
crumbs << @_id
|
|
87
|
+
Apipie.full_url crumbs.join('/')
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def api_url; "#{Apipie.api_base_url(_version)}#{@_path}"; end
|
|
91
|
+
|
|
92
|
+
def valid_method_name?(method_name)
|
|
93
|
+
@_methods.keys.map(&:to_s).include?(method_name.to_s)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def to_json(method_name = nil, lang = nil)
|
|
97
|
+
if method_name && !valid_method_name?(method_name)
|
|
98
|
+
raise "Method #{method_name} not found for resource #{_name}"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
methods = if method_name.blank?
|
|
102
|
+
@_methods.collect { |key, method_description| method_description.to_json(lang) }
|
|
103
|
+
else
|
|
104
|
+
[@_methods[method_name.to_sym].to_json(lang)]
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
{
|
|
108
|
+
:doc_url => doc_url,
|
|
109
|
+
:id => _id,
|
|
110
|
+
:api_url => api_url,
|
|
111
|
+
:name => @_name,
|
|
112
|
+
:short_description => Apipie.app.translate(@_short_description, lang),
|
|
113
|
+
:full_description => Apipie.app.translate(@_full_description, lang),
|
|
114
|
+
:version => _version,
|
|
115
|
+
:formats => @_formats,
|
|
116
|
+
:metadata => @_metadata,
|
|
117
|
+
:methods => methods,
|
|
118
|
+
:headers => _headers,
|
|
119
|
+
:deprecated => @_deprecated
|
|
120
|
+
}
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
module Apipie
|
|
2
|
+
|
|
3
|
+
class ResponseDescription
|
|
4
|
+
class ResponseObject
|
|
5
|
+
include Apipie::DSL::Base
|
|
6
|
+
include Apipie::DSL::Param
|
|
7
|
+
|
|
8
|
+
attr_accessor :additional_properties, :typename
|
|
9
|
+
|
|
10
|
+
def initialize(method_description, scope, block, typename)
|
|
11
|
+
@method_description = method_description
|
|
12
|
+
@scope = scope
|
|
13
|
+
@param_group = {scope: scope}
|
|
14
|
+
@additional_properties = false
|
|
15
|
+
@typename = typename
|
|
16
|
+
|
|
17
|
+
self.instance_exec(&block) if block
|
|
18
|
+
|
|
19
|
+
prepare_hash_params
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# this routine overrides Param#_default_param_group_scope and is called if Param#param_group is
|
|
23
|
+
# invoked during the instance_exec call in ResponseObject#initialize
|
|
24
|
+
def _default_param_group_scope
|
|
25
|
+
@scope
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def name
|
|
29
|
+
"response #{@code} for #{@method_description.method}"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def params_ordered
|
|
33
|
+
@params_ordered ||= _apipie_dsl_data[:params].map do |args|
|
|
34
|
+
options = args.find { |arg| arg.is_a? Hash }
|
|
35
|
+
options[:param_group] = @param_group
|
|
36
|
+
Apipie::ParamDescription.from_dsl_data(@method_description, args) unless options[:only_in] == :request
|
|
37
|
+
end.compact
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def prepare_hash_params
|
|
41
|
+
@hash_params = params_ordered.reduce({}) do |h, param|
|
|
42
|
+
h.update(param.name.to_sym => param)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class ResponseDescription
|
|
51
|
+
include Apipie::DSL::Base
|
|
52
|
+
include Apipie::DSL::Param
|
|
53
|
+
|
|
54
|
+
attr_reader :code, :description, :scope, :type_ref, :hash_validator, :is_array_of
|
|
55
|
+
|
|
56
|
+
def self.from_dsl_data(method_description, code, args)
|
|
57
|
+
options, scope, block, adapter = args
|
|
58
|
+
|
|
59
|
+
Apipie::ResponseDescription.new(method_description,
|
|
60
|
+
code,
|
|
61
|
+
options,
|
|
62
|
+
scope,
|
|
63
|
+
block,
|
|
64
|
+
adapter)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def is_array?
|
|
68
|
+
@is_array_of != false
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def typename
|
|
72
|
+
@response_object.typename
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def initialize(method_description, code, options, scope, block, adapter)
|
|
77
|
+
|
|
78
|
+
@type_ref = options[:param_group]
|
|
79
|
+
@is_array_of = options[:array_of] || false
|
|
80
|
+
raise ReturnsMultipleDefinitionError, options if @is_array_of && @type_ref
|
|
81
|
+
|
|
82
|
+
@type_ref ||= @is_array_of
|
|
83
|
+
|
|
84
|
+
@method_description = method_description
|
|
85
|
+
|
|
86
|
+
if code.is_a? Symbol
|
|
87
|
+
@code = Rack::Utils::SYMBOL_TO_STATUS_CODE[code]
|
|
88
|
+
else
|
|
89
|
+
@code = code
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
@description = options[:desc]
|
|
93
|
+
if @description.nil?
|
|
94
|
+
@description = Rack::Utils::HTTP_STATUS_CODES[@code]
|
|
95
|
+
raise "Cannot infer description from status code #{@code}" if @description.nil?
|
|
96
|
+
end
|
|
97
|
+
@scope = scope
|
|
98
|
+
|
|
99
|
+
if adapter
|
|
100
|
+
@response_object = adapter
|
|
101
|
+
else
|
|
102
|
+
@response_object = ResponseObject.new(method_description, scope, block, @type_ref)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
@response_object.additional_properties ||= options[:additional_properties]
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def param_description
|
|
109
|
+
nil
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def params_ordered
|
|
113
|
+
@response_object.params_ordered
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def additional_properties
|
|
117
|
+
!!@response_object.additional_properties
|
|
118
|
+
end
|
|
119
|
+
alias :allow_additional_properties :additional_properties
|
|
120
|
+
|
|
121
|
+
def to_json(lang=nil)
|
|
122
|
+
{
|
|
123
|
+
:code => code,
|
|
124
|
+
:description => description,
|
|
125
|
+
:is_array => is_array?,
|
|
126
|
+
:returns_object => params_ordered.map{ |param| param.to_json(lang).tap{|h| h.delete(:validations) }}.flatten,
|
|
127
|
+
:additional_properties => additional_properties,
|
|
128
|
+
}
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
module Apipie
|
|
2
|
+
|
|
3
|
+
def self.prop(name, expected_type, options={}, sub_properties=[])
|
|
4
|
+
Apipie::ResponseDescriptionAdapter::PropDesc.new(name, expected_type, options, sub_properties)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def self.additional_properties(yesno)
|
|
8
|
+
Apipie::ResponseDescriptionAdapter::AdditionalPropertiesModifier.new(yesno)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class ResponseDescriptionAdapter
|
|
12
|
+
class Modifier
|
|
13
|
+
def apply(adapter)
|
|
14
|
+
raise "Modifer subclass must implement 'apply' method"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class AdditionalPropertiesModifier < Modifier
|
|
19
|
+
def initialize(additional_properties_allowed)
|
|
20
|
+
@additional_properties_allowed = additional_properties_allowed
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def apply(adapter)
|
|
24
|
+
adapter.additional_properties = @additional_properties_allowed
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ResponseDescriptionAdapter
|
|
31
|
+
|
|
32
|
+
#
|
|
33
|
+
# A ResponseDescriptionAdapter::PropDesc object pretends to be an Apipie::Param in a ResponseDescription
|
|
34
|
+
#
|
|
35
|
+
# To successfully masquerade as such, it needs to:
|
|
36
|
+
# respond_to?('name') and/or ['name'] returning the name of the parameter
|
|
37
|
+
# respond_to?('required') and/or ['required'] returning boolean
|
|
38
|
+
# respond_to?('additional_properties') and/or ['additional_properties'] returning boolean
|
|
39
|
+
# respond_to?('validator') and/or ['validator'] returning 'nil' (so type is 'string'), or an object that:
|
|
40
|
+
# 1) describes a type. currently type is inferred as follows:
|
|
41
|
+
# if validator.is_a? Apipie::Validator::EnumValidator --> respond_to? 'values' (returns array). Type is enum or boolean
|
|
42
|
+
# else: use v.expected_type(). This is expected to be the swagger type, or:
|
|
43
|
+
# numeric ==> swagger type is 'number'
|
|
44
|
+
# hash ==> swagger type is 'object' and validator should respond_to? 'params_ordered'
|
|
45
|
+
# array ==> swagger type is array and validator (FUTURE) should indicate type of element
|
|
46
|
+
|
|
47
|
+
class PropDesc
|
|
48
|
+
|
|
49
|
+
def to_s
|
|
50
|
+
"PropDesc -- name: #{@name} type: #{@expected_type} required: #{@required} options: #{@options} subprop count: #{@sub_properties.length} additional properties: #{@additional_properties}"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
#
|
|
54
|
+
# a ResponseDescriptionAdapter::PropDesc::Validator pretends to be an Apipie::Validator
|
|
55
|
+
#
|
|
56
|
+
class Validator
|
|
57
|
+
attr_reader :expected_type
|
|
58
|
+
|
|
59
|
+
def [](key)
|
|
60
|
+
return self.send(key) if self.respond_to?(key.to_s)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def initialize(expected_type, enum_values=nil, sub_properties=nil)
|
|
64
|
+
@expected_type = expected_type
|
|
65
|
+
@enum_values = enum_values
|
|
66
|
+
@is_enum = !!enum_values
|
|
67
|
+
@sub_properties = sub_properties
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def is_enum?
|
|
71
|
+
!!@is_enum
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def values
|
|
75
|
+
@enum_values
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def params_ordered
|
|
79
|
+
raise "Only validators with expected_type 'object' can have sub-properties" unless @expected_type == 'object'
|
|
80
|
+
@sub_properties
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
#======================================================================
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def initialize(name, expected_type, options={}, sub_properties=[])
|
|
88
|
+
@name = name
|
|
89
|
+
@required = true
|
|
90
|
+
@required = false if options[:required] == false
|
|
91
|
+
@expected_type = expected_type
|
|
92
|
+
@additional_properties = false
|
|
93
|
+
|
|
94
|
+
options[:desc] ||= options[:description]
|
|
95
|
+
@description = options[:desc]
|
|
96
|
+
@options = options
|
|
97
|
+
@is_array = options[:is_array] || false
|
|
98
|
+
@sub_properties = []
|
|
99
|
+
for prop in sub_properties do
|
|
100
|
+
add_sub_property(prop)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def [](key)
|
|
105
|
+
return self.send(key) if self.respond_to?(key.to_s)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def add_sub_property(prop_desc)
|
|
109
|
+
raise "Only properties with expected_type 'object' can have sub-properties" unless @expected_type == 'object'
|
|
110
|
+
if prop_desc.is_a? PropDesc
|
|
111
|
+
@sub_properties << prop_desc
|
|
112
|
+
elsif prop_desc.is_a? Modifier
|
|
113
|
+
prop_desc.apply(self)
|
|
114
|
+
else
|
|
115
|
+
raise "Unrecognized prop_desc type (#{prop_desc.class})"
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def to_json(lang)
|
|
120
|
+
{
|
|
121
|
+
name: name,
|
|
122
|
+
required: required,
|
|
123
|
+
validator: validator,
|
|
124
|
+
description: description,
|
|
125
|
+
additional_properties: additional_properties,
|
|
126
|
+
is_array: is_array?,
|
|
127
|
+
options: options
|
|
128
|
+
}
|
|
129
|
+
end
|
|
130
|
+
attr_reader :name, :required, :expected_type, :options, :description
|
|
131
|
+
attr_accessor :additional_properties
|
|
132
|
+
|
|
133
|
+
alias_method :desc, :description
|
|
134
|
+
|
|
135
|
+
def is_array?
|
|
136
|
+
@is_array
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def validator
|
|
140
|
+
Validator.new(@expected_type, options[:values], @sub_properties)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
#======================================================================
|
|
146
|
+
|
|
147
|
+
class ResponseDescriptionAdapter
|
|
148
|
+
|
|
149
|
+
def self.from_self_describing_class(cls)
|
|
150
|
+
adapter = ResponseDescriptionAdapter.new(cls.to_s)
|
|
151
|
+
props = cls.describe_own_properties
|
|
152
|
+
adapter.add_property_descriptions(props)
|
|
153
|
+
adapter
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def initialize(typename)
|
|
157
|
+
@property_descs = []
|
|
158
|
+
@additional_properties = false
|
|
159
|
+
@typename = typename
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
attr_accessor :additional_properties, :typename
|
|
163
|
+
|
|
164
|
+
def allow_additional_properties
|
|
165
|
+
additional_properties
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def to_json
|
|
169
|
+
params_ordered.to_json
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def add(prop_desc)
|
|
173
|
+
if prop_desc.is_a? PropDesc
|
|
174
|
+
@property_descs << prop_desc
|
|
175
|
+
elsif prop_desc.is_a? Modifier
|
|
176
|
+
prop_desc.apply(self)
|
|
177
|
+
else
|
|
178
|
+
raise "Unrecognized prop_desc type (#{prop_desc.class})"
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def add_property_descriptions(prop_descs)
|
|
183
|
+
for prop_desc in prop_descs
|
|
184
|
+
add(prop_desc)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def property(name, expected_type, options)
|
|
189
|
+
@property_descs << PropDesc.new(name, expected_type, options)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def params_ordered
|
|
193
|
+
@property_descs
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def is_array?
|
|
197
|
+
false
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|