grape-swagger 0.33.0 → 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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -7
  3. data/.rubocop_todo.yml +0 -6
  4. data/.travis.yml +11 -10
  5. data/CHANGELOG.md +75 -5
  6. data/Gemfile +5 -5
  7. data/README.md +73 -5
  8. data/grape-swagger.gemspec +1 -1
  9. data/lib/grape-swagger/doc_methods/build_model_definition.rb +0 -17
  10. data/lib/grape-swagger/doc_methods/data_type.rb +1 -1
  11. data/lib/grape-swagger/doc_methods/extensions.rb +6 -1
  12. data/lib/grape-swagger/doc_methods/format_data.rb +51 -0
  13. data/lib/grape-swagger/doc_methods/move_params.rb +22 -49
  14. data/lib/grape-swagger/doc_methods/parse_params.rb +6 -0
  15. data/lib/grape-swagger/doc_methods.rb +2 -0
  16. data/lib/grape-swagger/endpoint/params_parser.rb +22 -22
  17. data/lib/grape-swagger/endpoint.rb +33 -14
  18. data/lib/grape-swagger/version.rb +1 -1
  19. data/lib/grape-swagger.rb +1 -1
  20. data/spec/issues/751_deeply_nested_objects_spec.rb +190 -0
  21. data/spec/lib/data_type_spec.rb +2 -2
  22. data/spec/lib/endpoint/params_parser_spec.rb +46 -21
  23. data/spec/lib/endpoint_spec.rb +4 -4
  24. data/spec/lib/extensions_spec.rb +10 -0
  25. data/spec/lib/format_data_spec.rb +91 -0
  26. data/spec/lib/move_params_spec.rb +4 -266
  27. data/spec/lib/optional_object_spec.rb +0 -1
  28. data/spec/spec_helper.rb +1 -1
  29. data/spec/support/model_parsers/entity_parser.rb +1 -1
  30. data/spec/support/model_parsers/representable_parser.rb +1 -1
  31. data/spec/swagger_v2/api_swagger_v2_hash_and_array_spec.rb +3 -1
  32. data/spec/swagger_v2/api_swagger_v2_hide_param_spec.rb +14 -3
  33. data/spec/swagger_v2/api_swagger_v2_response_with_root_spec.rb +153 -0
  34. data/spec/swagger_v2/boolean_params_spec.rb +1 -1
  35. data/spec/swagger_v2/description_not_initialized_spec.rb +39 -0
  36. data/spec/swagger_v2/endpoint_versioned_path_spec.rb +33 -0
  37. data/spec/swagger_v2/mounted_target_class_spec.rb +1 -1
  38. data/spec/swagger_v2/namespace_tags_prefix_spec.rb +15 -1
  39. data/spec/swagger_v2/params_array_spec.rb +2 -2
  40. data/spec/swagger_v2/parent_less_namespace_spec.rb +32 -0
  41. data/spec/swagger_v2/{reference_entity.rb → reference_entity_spec.rb} +17 -10
  42. metadata +20 -13
  43. data/spec/swagger_v2/description_not_initialized.rb +0 -39
  44. data/spec/swagger_v2/parent_less_namespace.rb +0 -49
@@ -87,7 +87,12 @@ module GrapeSwagger
87
87
  part.select { |x| x == identifier }
88
88
  end
89
89
 
90
- def method
90
+ def method(*args)
91
+ # We're shadowing Object.method(:symbol) here so we provide
92
+ # a compatibility layer for code that introspects the methods
93
+ # of this class
94
+ return super if args.size.positive?
95
+
91
96
  @route.request_method.downcase.to_sym
92
97
  end
93
98
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GrapeSwagger
4
+ module DocMethods
5
+ class FormatData
6
+ class << self
7
+ def to_format(parameters)
8
+ parameters.reject { |parameter| parameter[:in] == 'body' }.each do |b|
9
+ related_parameters = parameters.select do |p|
10
+ p[:name] != b[:name] && p[:name].to_s.include?(b[:name].to_s.gsub(/\[\]\z/, '') + '[')
11
+ end
12
+ parameters.reject! { |p| p[:name] == b[:name] } if move_down(b, related_parameters)
13
+ end
14
+ parameters
15
+ end
16
+
17
+ def move_down(parameter, related_parameters)
18
+ case parameter[:type]
19
+ when 'array'
20
+ add_array(parameter, related_parameters)
21
+ unless related_parameters.blank?
22
+ add_braces(parameter, related_parameters) if parameter[:name].match?(/\A.*\[\]\z/)
23
+ return true
24
+ end
25
+ when 'object'
26
+ return true
27
+ end
28
+ false
29
+ end
30
+
31
+ def add_braces(parameter, related_parameters)
32
+ param_name = parameter[:name].gsub(/\A(.*)\[\]\z/, '\1')
33
+ related_parameters.each { |p| p[:name] = p[:name].gsub(param_name, param_name + '[]') }
34
+ end
35
+
36
+ def add_array(parameter, related_parameters)
37
+ related_parameters.each do |p|
38
+ p_type = p[:type] == 'array' ? 'string' : p[:type]
39
+ p[:items] = { type: p_type, format: p[:format], enum: p[:enum], is_array: p[:is_array] }
40
+ p[:items].delete_if { |_k, v| v.nil? }
41
+ p[:type] = 'array'
42
+ p[:is_array] = parameter[:is_array]
43
+ p.delete(:format)
44
+ p.delete(:enum)
45
+ p.delete_if { |_k, v| v.nil? }
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -8,7 +8,7 @@ module GrapeSwagger
8
8
  class << self
9
9
  attr_accessor :definitions
10
10
 
11
- def can_be_moved?(params, http_verb)
11
+ def can_be_moved?(http_verb, params)
12
12
  move_methods.include?(http_verb) && includes_body_param?(params)
13
13
  end
14
14
 
@@ -51,22 +51,33 @@ module GrapeSwagger
51
51
 
52
52
  def move_params_to_new(definition, params)
53
53
  params, nested_params = params.partition { |x| !x[:name].to_s.include?('[') }
54
-
55
- unless params.blank?
56
- properties, required = build_properties(params)
57
- add_properties_to_definition(definition, properties, required)
54
+ params.each do |param|
55
+ property = param[:name]
56
+ param_properties, param_required = build_properties([param])
57
+ add_properties_to_definition(definition, param_properties, param_required)
58
+ related_nested_params, nested_params = nested_params.partition { |x| x[:name].start_with?("#{property}[") }
59
+ prepare_nested_names(property, related_nested_params)
60
+
61
+ next if related_nested_params.blank?
62
+
63
+ nested_definition = if should_expose_as_array?([param])
64
+ move_params_to_new(array_type, related_nested_params)
65
+ else
66
+ move_params_to_new(object_type, related_nested_params)
67
+ end
68
+ if definition.key?(:items)
69
+ definition[:items][:properties][property.to_sym].deep_merge!(nested_definition)
70
+ else
71
+ definition[:properties][property.to_sym].deep_merge!(nested_definition)
72
+ end
58
73
  end
59
-
60
- nested_properties = build_nested_properties(nested_params) unless nested_params.blank?
61
- add_properties_to_definition(definition, nested_properties, []) unless nested_params.blank?
74
+ definition
62
75
  end
63
76
 
64
77
  def build_properties(params)
65
78
  properties = {}
66
79
  required = []
67
80
 
68
- prepare_nested_types(params) if should_expose_as_array?(params)
69
-
70
81
  params.each do |param|
71
82
  name = param[:name].to_sym
72
83
 
@@ -103,28 +114,6 @@ module GrapeSwagger
103
114
  end
104
115
  end
105
116
 
106
- def build_nested_properties(params, properties = {})
107
- property = params.bsearch { |x| x[:name].include?('[') }[:name].split('[').first
108
-
109
- nested_params, params = params.partition { |x| x[:name].start_with?("#{property}[") }
110
- prepare_nested_names(property, nested_params)
111
-
112
- recursive_call(properties, property, nested_params) unless nested_params.empty?
113
- build_nested_properties(params, properties) unless params.empty?
114
-
115
- properties
116
- end
117
-
118
- def recursive_call(properties, property, nested_params)
119
- if should_expose_as_array?(nested_params)
120
- properties[property.to_sym] = array_type
121
- move_params_to_new(properties[property.to_sym][:items], nested_params)
122
- else
123
- properties[property.to_sym] = object_type
124
- move_params_to_new(properties[property.to_sym], nested_params)
125
- end
126
- end
127
-
128
117
  def movable_params(params)
129
118
  to_delete = params.each_with_object([]) { |x, memo| memo << x if deletable?(x) }
130
119
  delete_from(params, to_delete)
@@ -177,22 +166,6 @@ module GrapeSwagger
177
166
  { type: 'object', properties: {} }
178
167
  end
179
168
 
180
- def prepare_nested_types(params)
181
- params.each do |param|
182
- next unless param[:items]
183
-
184
- param[:type] = if param[:items][:type] == 'array'
185
- 'string'
186
- elsif param[:items].key?('$ref')
187
- param[:type] = 'object'
188
- else
189
- param[:items][:type]
190
- end
191
- param[:format] = param[:items][:format] if param[:items][:format]
192
- param.delete(:items) if param[:type] != 'object'
193
- end
194
- end
195
-
196
169
  def prepare_nested_names(property, params)
197
170
  params.each { |x| x[:name] = x[:name].sub(property, '').sub('[', '').sub(']', '') }
198
171
  end
@@ -208,7 +181,7 @@ module GrapeSwagger
208
181
  end
209
182
 
210
183
  def property_keys
211
- %i[type format description minimum maximum items enum default]
184
+ %i[type format description minimum maximum items enum default additionalProperties]
212
185
  end
213
186
 
214
187
  def deletable?(param)
@@ -25,6 +25,7 @@ module GrapeSwagger
25
25
  document_default_value(settings) unless value_type[:is_array]
26
26
  document_range_values(settings) unless value_type[:is_array]
27
27
  document_required(settings)
28
+ document_additional_properties(settings)
28
29
 
29
30
  @parsed_param
30
31
  end
@@ -91,6 +92,11 @@ module GrapeSwagger
91
92
  @parsed_param[:collectionFormat] = collection_format if DataType.collections.include?(collection_format)
92
93
  end
93
94
 
95
+ def document_additional_properties(settings)
96
+ additional_properties = settings[:additionalProperties]
97
+ @parsed_param[:additionalProperties] = additional_properties if additional_properties
98
+ end
99
+
94
100
  def param_type(value_type)
95
101
  param_type = value_type[:param_type] || value_type[:in]
96
102
  if value_type[:path].include?("{#{value_type[:param_name]}}")
@@ -4,6 +4,7 @@ require 'grape-swagger/doc_methods/status_codes'
4
4
  require 'grape-swagger/doc_methods/produces_consumes'
5
5
  require 'grape-swagger/doc_methods/data_type'
6
6
  require 'grape-swagger/doc_methods/extensions'
7
+ require 'grape-swagger/doc_methods/format_data'
7
8
  require 'grape-swagger/doc_methods/operation_id'
8
9
  require 'grape-swagger/doc_methods/optional_object'
9
10
  require 'grape-swagger/doc_methods/path_string'
@@ -102,6 +103,7 @@ module GrapeSwagger
102
103
  base_path: nil,
103
104
  add_base_path: false,
104
105
  add_version: true,
106
+ add_root: false,
105
107
  hide_documentation_path: true,
106
108
  format: :json,
107
109
  authorizations: nil,
@@ -3,49 +3,37 @@
3
3
  module GrapeSwagger
4
4
  module Endpoint
5
5
  class ParamsParser
6
- attr_reader :params, :settings
6
+ attr_reader :params, :settings, :endpoint
7
7
 
8
- def self.parse_request_params(params, settings)
9
- new(params, settings).parse_request_params
8
+ def self.parse_request_params(params, settings, endpoint)
9
+ new(params, settings, endpoint).parse_request_params
10
10
  end
11
11
 
12
- def initialize(params, settings)
12
+ def initialize(params, settings, endpoint)
13
13
  @params = params
14
14
  @settings = settings
15
+ @endpoint = endpoint
15
16
  end
16
17
 
17
18
  def parse_request_params
18
- array_keys = []
19
19
  public_params.each_with_object({}) do |(name, options), memo|
20
20
  name = name.to_s
21
21
  param_type = options[:type]
22
22
  param_type = param_type.to_s unless param_type.nil?
23
23
 
24
24
  if param_type_is_array?(param_type)
25
- array_keys << name
26
25
  options[:is_array] = true
27
-
28
- name += '[]' if array_use_braces?(options)
29
- else
30
- keys = array_keys.find_all { |key| name.start_with? "#{key}[" }
31
- if keys.any?
32
- options[:is_array] = true
33
- if array_use_braces?(options)
34
- keys.sort.reverse_each do |key|
35
- name = name.sub(key, "#{key}[]")
36
- end
37
- end
38
- end
26
+ name += '[]' if array_use_braces?
39
27
  end
40
28
 
41
- memo[name] = options unless %w[Hash Array].include?(param_type) && !options.key?(:documentation)
29
+ memo[name] = options
42
30
  end
43
31
  end
44
32
 
45
33
  private
46
34
 
47
- def array_use_braces?(options)
48
- settings[:array_use_braces] && !(options[:documentation] && options[:documentation][:param_type] == 'body')
35
+ def array_use_braces?
36
+ @array_use_braces ||= settings[:array_use_braces] && !includes_body_param?
49
37
  end
50
38
 
51
39
  def param_type_is_array?(param_type)
@@ -68,9 +56,21 @@ module GrapeSwagger
68
56
  return true unless param_options.key?(:documentation) && !param_options[:required]
69
57
 
70
58
  param_hidden = param_options[:documentation].fetch(:hidden, false)
71
- param_hidden = param_hidden.call if param_hidden.is_a?(Proc)
59
+ if param_hidden.is_a?(Proc)
60
+ param_hidden = if settings[:token_owner]
61
+ param_hidden.call(endpoint.send(settings[:token_owner].to_sym))
62
+ else
63
+ param_hidden.call
64
+ end
65
+ end
72
66
  !param_hidden
73
67
  end
68
+
69
+ def includes_body_param?
70
+ params.any? do |_, options|
71
+ options.dig(:documentation, :param_type) == 'body' || options.dig(:documentation, :in) == 'body'
72
+ end
73
+ end
74
74
  end
75
75
  end
76
76
  end
@@ -78,8 +78,7 @@ module Grape
78
78
  def path_and_definition_objects(namespace_routes, options)
79
79
  @paths = {}
80
80
  @definitions = {}
81
- namespace_routes.each_key do |key|
82
- routes = namespace_routes[key]
81
+ namespace_routes.each_value do |routes|
83
82
  path_item(routes, options)
84
83
  end
85
84
 
@@ -121,7 +120,7 @@ module Grape
121
120
  method[:consumes] = consumes_object(route, options[:format])
122
121
  method[:parameters] = params_object(route, options, path)
123
122
  method[:security] = security_object(route)
124
- method[:responses] = response_object(route)
123
+ method[:responses] = response_object(route, options)
125
124
  method[:tags] = route.options.fetch(:tags, tag_object(route, path))
126
125
  method[:operationId] = GrapeSwagger::DocMethods::OperationId.build(route, path)
127
126
  method[:deprecated] = deprecated_object(route)
@@ -179,22 +178,24 @@ module Grape
179
178
  parameters = partition_params(route, options).map do |param, value|
180
179
  value = { required: false }.merge(value) if value.is_a?(Hash)
181
180
  _, value = default_type([[param, value]]).first if value == ''
182
- if value[:type]
183
- expose_params(value[:type])
184
- elsif value[:documentation]
181
+ if value.dig(:documentation, :type)
185
182
  expose_params(value[:documentation][:type])
183
+ elsif value[:type]
184
+ expose_params(value[:type])
186
185
  end
187
186
  GrapeSwagger::DocMethods::ParseParams.call(param, value, path, route, @definitions)
188
187
  end
189
188
 
190
- if GrapeSwagger::DocMethods::MoveParams.can_be_moved?(parameters, route.request_method)
189
+ if GrapeSwagger::DocMethods::MoveParams.can_be_moved?(route.request_method, parameters)
191
190
  parameters = GrapeSwagger::DocMethods::MoveParams.to_definition(path, parameters, route, @definitions)
192
191
  end
193
192
 
193
+ GrapeSwagger::DocMethods::FormatData.to_format(parameters)
194
+
194
195
  parameters.presence
195
196
  end
196
197
 
197
- def response_object(route)
198
+ def response_object(route, options)
198
199
  codes = http_codes_from_route(route)
199
200
  codes.map! { |x| x.is_a?(Array) ? { code: x[0], message: x[1], model: x[2], examples: x[3], headers: x[4] } : x }
200
201
 
@@ -219,7 +220,7 @@ module Grape
219
220
 
220
221
  @definitions[response_model][:description] = description_object(route)
221
222
 
222
- memo[value[:code]][:schema] = build_reference(route, value, response_model)
223
+ memo[value[:code]][:schema] = build_reference(route, value, response_model, options)
223
224
  memo[value[:code]][:examples] = value[:examples] if value[:examples]
224
225
  end
225
226
  end
@@ -250,20 +251,38 @@ module Grape
250
251
  def tag_object(route, path)
251
252
  version = GrapeSwagger::DocMethods::Version.get(route)
252
253
  version = [version] unless version.is_a?(Array)
253
-
254
+ prefix = route.prefix.to_s.split('/').reject(&:empty?)
254
255
  Array(
255
256
  path.split('{')[0].split('/').reject(&:empty?).delete_if do |i|
256
- i == route.prefix.to_s || version.map(&:to_s).include?(i)
257
+ prefix.include?(i) || version.map(&:to_s).include?(i)
257
258
  end.first
258
259
  ).presence
259
260
  end
260
261
 
261
262
  private
262
263
 
263
- def build_reference(route, value, response_model)
264
+ def build_reference(route, value, response_model, settings)
264
265
  # TODO: proof that the definition exist, if model isn't specified
265
266
  reference = { '$ref' => "#/definitions/#{response_model}" }
266
- route.options[:is_array] && value[:code] < 300 ? { type: 'array', items: reference } : reference
267
+ return reference unless value[:code] < 300
268
+
269
+ reference = { type: 'array', items: reference } if route.options[:is_array]
270
+ build_root(route, reference, response_model, settings)
271
+ end
272
+
273
+ def build_root(route, reference, response_model, settings)
274
+ default_root = response_model.underscore
275
+ default_root = default_root.pluralize if route.options[:is_array]
276
+ case route.settings.dig(:swagger, :root)
277
+ when true
278
+ { type: 'object', properties: { default_root => reference } }
279
+ when false
280
+ reference
281
+ when nil
282
+ settings[:add_root] ? { type: 'object', properties: { default_root => reference } } : reference
283
+ else
284
+ { type: 'object', properties: { route.settings.dig(:swagger, :root) => reference } }
285
+ end
267
286
  end
268
287
 
269
288
  def file_response?(value)
@@ -282,7 +301,7 @@ module Grape
282
301
  default_type(required)
283
302
 
284
303
  request_params = unless declared_params.nil? && route.headers.nil?
285
- GrapeSwagger::Endpoint::ParamsParser.parse_request_params(required, settings)
304
+ GrapeSwagger::Endpoint::ParamsParser.parse_request_params(required, settings, self)
286
305
  end || {}
287
306
 
288
307
  request_params.empty? ? required : request_params
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GrapeSwagger
4
- VERSION = '0.33.0'
4
+ VERSION = '1.0.0'
5
5
  end
data/lib/grape-swagger.rb CHANGED
@@ -26,7 +26,7 @@ module SwaggerRouting
26
26
  def combine_routes(app, doc_klass)
27
27
  app.routes.each do |route|
28
28
  route_path = route.path
29
- route_match = route_path.split(/^.*?#{route.prefix.to_s}/).last
29
+ route_match = route_path.split(/^.*?#{route.prefix}/).last
30
30
  next unless route_match
31
31
 
32
32
  route_match = route_match.match('\/([\w|-]*?)[\.\/\(]') || route_match.match('\/([\w|-]*)$')
@@ -0,0 +1,190 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe '751 deeply nested objects' do
6
+ let(:app) do
7
+ Class.new(Grape::API) do
8
+ content_type :json, 'application/json; charset=UTF-8'
9
+ default_format :json
10
+ class Vrp < Grape::API
11
+ def self.vrp_request_timewindow(this)
12
+ this.optional(:start, types: [String, Float, Integer])
13
+ this.optional(:end, types: [String, Float, Integer])
14
+ end
15
+
16
+ def self.vrp_request_point(this)
17
+ this.requires(:id, type: String, allow_blank: false)
18
+ this.optional(:matrix_index, type: Integer)
19
+ this.optional(:location, type: Hash) do
20
+ requires(:lat, type: Float, allow_blank: false)
21
+ requires(:lon, type: Float, allow_blank: false)
22
+ end
23
+ this.at_least_one_of :matrix_index, :location
24
+ end
25
+
26
+ def self.vrp_request_activity(this)
27
+ this.optional(:duration, types: [String, Float, Integer])
28
+ this.requires(:point_id, type: String, allow_blank: false)
29
+ this.optional(:timewindows, type: Array) do
30
+ Vrp.vrp_request_timewindow(self)
31
+ end
32
+ end
33
+
34
+ def self.vrp_request_service(this)
35
+ this.requires(:id, type: String, allow_blank: false)
36
+ this.optional(:skills, type: Array[String])
37
+
38
+ this.optional(:activity, type: Hash) do
39
+ Vrp.vrp_request_activity(self)
40
+ end
41
+ this.optional(:activities, type: Array) do
42
+ Vrp.vrp_request_activity(self)
43
+ end
44
+ this.mutually_exclusive :activity, :activities
45
+ end
46
+ end
47
+
48
+ namespace :vrp do
49
+ resource :submit do
50
+ desc 'Submit Problems', nickname: 'vrp'
51
+ params do
52
+ optional(:vrp, type: Hash, documentation: { param_type: 'body' }) do
53
+ optional(:points, type: Array) do
54
+ Vrp.vrp_request_point(self)
55
+ end
56
+
57
+ optional(:services, type: Array) do
58
+ Vrp.vrp_request_service(self)
59
+ end
60
+ end
61
+ end
62
+ post do
63
+ { vrp: params[:vrp] }.to_json
64
+ end
65
+ end
66
+ end
67
+
68
+ add_swagger_documentation format: :json
69
+ end
70
+ end
71
+
72
+ subject do
73
+ get '/swagger_doc'
74
+ JSON.parse(last_response.body)
75
+ end
76
+
77
+ describe 'Correctness of vrp Points' do
78
+ let(:get_points_response) { subject['definitions']['postVrpSubmit']['properties']['vrp']['properties']['points'] }
79
+ specify do
80
+ expect(get_points_response).to eql(
81
+ 'type' => 'array',
82
+ 'items' => {
83
+ 'type' => 'object',
84
+ 'properties' => {
85
+ 'id' => {
86
+ 'type' => 'string'
87
+ },
88
+ 'matrix_index' => {
89
+ 'type' => 'integer',
90
+ 'format' => 'int32'
91
+ },
92
+ 'location' => {
93
+ 'type' => 'object',
94
+ 'properties' => {
95
+ 'lat' => {
96
+ 'type' => 'number',
97
+ 'format' => 'float'
98
+ },
99
+ 'lon' => {
100
+ 'type' => 'number',
101
+ 'format' => 'float'
102
+ }
103
+ },
104
+ 'required' => %w[lat lon]
105
+ }
106
+ },
107
+ 'required' => ['id']
108
+ }
109
+ )
110
+ end
111
+ end
112
+
113
+ describe 'Correctness of vrp Services' do
114
+ let(:get_service_response) { subject['definitions']['postVrpSubmit']['properties']['vrp']['properties']['services'] }
115
+ specify do
116
+ expect(get_service_response).to include(
117
+ 'type' => 'array',
118
+ 'items' => {
119
+ 'type' => 'object',
120
+ 'properties' => {
121
+ 'id' => {
122
+ 'type' => 'string'
123
+ },
124
+ 'skills' => {
125
+ 'type' => 'array',
126
+ 'items' => {
127
+ 'type' => 'string'
128
+ }
129
+ },
130
+ 'activity' => {
131
+ 'type' => 'object',
132
+ 'properties' => {
133
+ 'duration' => {
134
+ 'type' => 'string'
135
+ },
136
+ 'point_id' => {
137
+ 'type' => 'string'
138
+ },
139
+ 'timewindows' => {
140
+ 'type' => 'array',
141
+ 'items' => {
142
+ 'type' => 'object',
143
+ 'properties' => {
144
+ 'start' => {
145
+ 'type' => 'string'
146
+ },
147
+ 'end' => {
148
+ 'type' => 'string'
149
+ }
150
+ }
151
+ }
152
+ }
153
+ },
154
+ 'required' => ['point_id']
155
+ }, 'activities' => {
156
+ 'type' => 'array',
157
+ 'items' => {
158
+ 'type' => 'object',
159
+ 'properties' => {
160
+ 'duration' => {
161
+ 'type' => 'string'
162
+ },
163
+ 'point_id' => {
164
+ 'type' => 'string'
165
+ },
166
+ 'timewindows' => {
167
+ 'type' => 'array',
168
+ 'items' => {
169
+ 'type' => 'object',
170
+ 'properties' => {
171
+ 'start' => {
172
+ 'type' => 'string'
173
+ },
174
+ 'end' => {
175
+ 'type' => 'string'
176
+ }
177
+ }
178
+ }
179
+ }
180
+ },
181
+ 'required' => ['point_id']
182
+ }
183
+ }
184
+ },
185
+ 'required' => ['id']
186
+ }
187
+ )
188
+ end
189
+ end
190
+ end
@@ -55,8 +55,8 @@ describe GrapeSwagger::DocMethods::DataType do
55
55
  it { is_expected.to eq 'file' }
56
56
  end
57
57
 
58
- describe 'Virtus::Attribute::Boolean' do
59
- let(:value) { { type: Virtus::Attribute::Boolean } }
58
+ describe 'Grape::API::Boolean' do
59
+ let(:value) { { type: Grape::API::Boolean } }
60
60
 
61
61
  it { is_expected.to eq 'boolean' }
62
62
  end