ruby-swagger 0.0.3 → 0.1.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/lib/ruby-swagger.rb +1 -5
- data/lib/ruby-swagger/data/contact.rb +3 -8
- data/lib/ruby-swagger/data/definitions.rb +5 -7
- data/lib/ruby-swagger/data/document.rb +22 -24
- data/lib/ruby-swagger/data/example.rb +3 -5
- data/lib/ruby-swagger/data/external_documentation.rb +4 -6
- data/lib/ruby-swagger/data/header.rb +2 -4
- data/lib/ruby-swagger/data/headers.rb +5 -8
- data/lib/ruby-swagger/data/info.rb +6 -8
- data/lib/ruby-swagger/data/items.rb +4 -6
- data/lib/ruby-swagger/data/license.rb +4 -6
- data/lib/ruby-swagger/data/mime.rb +0 -2
- data/lib/ruby-swagger/data/operation.rb +7 -9
- data/lib/ruby-swagger/data/parameter.rb +4 -10
- data/lib/ruby-swagger/data/parameters.rb +4 -6
- data/lib/ruby-swagger/data/path.rb +14 -18
- data/lib/ruby-swagger/data/paths.rb +5 -7
- data/lib/ruby-swagger/data/reference.rb +4 -8
- data/lib/ruby-swagger/data/response.rb +1 -3
- data/lib/ruby-swagger/data/responses.rb +1 -3
- data/lib/ruby-swagger/data/schema.rb +7 -9
- data/lib/ruby-swagger/data/scopes.rb +4 -6
- data/lib/ruby-swagger/data/security_definitions.rb +5 -7
- data/lib/ruby-swagger/data/security_requirement.rb +6 -8
- data/lib/ruby-swagger/data/security_scheme.rb +10 -12
- data/lib/ruby-swagger/data/tag.rb +3 -5
- data/lib/ruby-swagger/data/url.rb +1 -3
- data/lib/ruby-swagger/data/xml_object.rb +2 -4
- data/lib/ruby-swagger/grape/entity.rb +41 -0
- data/lib/ruby-swagger/grape/entity_exposure.rb +96 -0
- data/lib/ruby-swagger/grape/entity_nesting_exposure.rb +38 -0
- data/lib/ruby-swagger/grape/grape.rb +1 -1
- data/lib/ruby-swagger/grape/grape_config.rb +19 -22
- data/lib/ruby-swagger/grape/grape_presenter.rb +6 -9
- data/lib/ruby-swagger/grape/grape_template.rb +3 -5
- data/lib/ruby-swagger/grape/method.rb +79 -71
- data/lib/ruby-swagger/grape/param.rb +3 -3
- data/lib/ruby-swagger/grape/route_path.rb +1 -3
- data/lib/ruby-swagger/grape/routes.rb +6 -9
- data/lib/ruby-swagger/grape/type.rb +46 -119
- data/lib/ruby-swagger/io/comparable.rb +13 -16
- data/lib/ruby-swagger/io/definitions.rb +5 -11
- data/lib/ruby-swagger/io/file_system.rb +8 -9
- data/lib/ruby-swagger/io/paths.rb +6 -11
- data/lib/ruby-swagger/io/security.rb +3 -6
- data/lib/ruby-swagger/object.rb +5 -7
- data/lib/ruby-swagger/railtie.rb +1 -1
- data/lib/ruby-swagger/template.rb +2 -4
- data/lib/tasks/swagger.rake +13 -18
- metadata +10 -7
@@ -1,8 +1,7 @@
|
|
1
1
|
require 'ruby-swagger/object'
|
2
2
|
|
3
3
|
module Swagger::Data
|
4
|
-
class SecurityRequirement < Swagger::Object #https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#securityRequirementObject
|
5
|
-
|
4
|
+
class SecurityRequirement < Swagger::Object # https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#securityRequirementObject
|
6
5
|
def initialize
|
7
6
|
@requirements = {}
|
8
7
|
end
|
@@ -11,14 +10,14 @@ module Swagger::Data
|
|
11
10
|
return nil unless security
|
12
11
|
|
13
12
|
s = Swagger::Data::SecurityRequirement.new
|
14
|
-
security.each {|key, reqs| s.add_requirement(key, reqs)}
|
13
|
+
security.each { |key, reqs| s.add_requirement(key, reqs) }
|
15
14
|
s
|
16
15
|
end
|
17
16
|
|
18
17
|
def add_requirement(key, requirements)
|
19
|
-
raise
|
20
|
-
raise
|
21
|
-
raise
|
18
|
+
raise ArgumentError.new('Swagger::Data::SecurityRequirement#add_requirement - key is nil') unless key
|
19
|
+
raise ArgumentError.new('Swagger::Data::SecurityRequirement#add_requirement - requirements is nil') unless requirements
|
20
|
+
raise ArgumentError.new('Swagger::Data::SecurityRequirement#add_requirement - requirements is not an array') unless requirements.is_a?(Array)
|
22
21
|
|
23
22
|
@requirements[key] = requirements
|
24
23
|
end
|
@@ -30,6 +29,5 @@ module Swagger::Data
|
|
30
29
|
def as_swagger
|
31
30
|
@requirements
|
32
31
|
end
|
33
|
-
|
34
32
|
end
|
35
|
-
end
|
33
|
+
end
|
@@ -2,8 +2,7 @@ require 'ruby-swagger/object'
|
|
2
2
|
require 'ruby-swagger/data/scopes'
|
3
3
|
|
4
4
|
module Swagger::Data
|
5
|
-
class SecurityScheme < Swagger::Object #https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#securitySchemeObject
|
6
|
-
|
5
|
+
class SecurityScheme < Swagger::Object # https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#securitySchemeObject
|
7
6
|
attr_swagger :type, :description, :name, :in, :flow, :authorizationUrl, :tokenUrl, :scopes
|
8
7
|
|
9
8
|
def self.parse(security)
|
@@ -13,21 +12,21 @@ module Swagger::Data
|
|
13
12
|
end
|
14
13
|
|
15
14
|
def type=(new_type)
|
16
|
-
raise ArgumentError.new(
|
15
|
+
raise ArgumentError.new('Security::Data::SecurityScheme#type= - type is nil') unless new_type
|
17
16
|
raise ArgumentError.new("Security::Data::SecurityScheme#type= - unrecognized type #{new_type}") unless %w(basic apiKey oauth2).include?(new_type)
|
18
17
|
|
19
18
|
@type = new_type
|
20
19
|
end
|
21
20
|
|
22
21
|
def name=(new_name)
|
23
|
-
raise ArgumentError.new(
|
22
|
+
raise ArgumentError.new('Security::Data::SecurityScheme#name= - name is nil') if @type == 'apiKey' && !new_name
|
24
23
|
|
25
24
|
@name = new_name
|
26
25
|
end
|
27
26
|
|
28
27
|
def in=(new_in)
|
29
28
|
if @type == 'apiKey'
|
30
|
-
raise ArgumentError.new(
|
29
|
+
raise ArgumentError.new('Security::Data::SecurityScheme#in= - in is nil') unless new_in
|
31
30
|
raise ArgumentError.new("Security::Data::SecurityScheme#in= - unrecognized in #{new_in}") unless %w(query header).include?(new_in)
|
32
31
|
end
|
33
32
|
|
@@ -36,7 +35,7 @@ module Swagger::Data
|
|
36
35
|
|
37
36
|
def flow=(new_flow)
|
38
37
|
if @type == 'oauth2'
|
39
|
-
raise ArgumentError.new(
|
38
|
+
raise ArgumentError.new('Security::Data::SecurityScheme#flow= - flow is nil') unless new_flow
|
40
39
|
raise ArgumentError.new("Security::Data::SecurityScheme#flow= - unrecognized flow #{new_flow}") unless %w(implicit password application accessCode).include?(new_flow)
|
41
40
|
end
|
42
41
|
|
@@ -44,24 +43,23 @@ module Swagger::Data
|
|
44
43
|
end
|
45
44
|
|
46
45
|
def authorizationUrl=(new_authorizationUrl)
|
47
|
-
raise ArgumentError.new(
|
46
|
+
raise ArgumentError.new('Security::Data::SecurityScheme#authorizationUrl= - authorizationUrl is nil') if @type == 'oauth2' && (@flow == 'implicit' || @flow == 'accessCode') && !new_authorizationUrl
|
48
47
|
|
49
48
|
@authorizationUrl = new_authorizationUrl
|
50
49
|
end
|
51
50
|
|
52
51
|
def tokenUrl=(new_tokenUrl)
|
53
|
-
raise ArgumentError.new(
|
52
|
+
raise ArgumentError.new('Security::Data::SecurityScheme#tokenUrl= - tokenUrl is nil') if @type == 'oauth2' && (@flow == 'password' || @flow == 'application' || @flow == 'accessCode') && !new_tokenUrl
|
54
53
|
|
55
54
|
@tokenUrl = new_tokenUrl
|
56
55
|
end
|
57
56
|
|
58
57
|
def scopes=(new_scopes)
|
59
|
-
raise ArgumentError.new(
|
58
|
+
raise ArgumentError.new('Security::Data::SecurityScheme#scopes= - scopes is nil') if @type == 'oauth2' && !new_scopes
|
60
59
|
|
61
|
-
new_scopes = Swagger::Data::Scopes.parse(new_scopes)
|
60
|
+
new_scopes = Swagger::Data::Scopes.parse(new_scopes) unless new_scopes.is_a?(Swagger::Data::Scopes)
|
62
61
|
|
63
62
|
@scopes = new_scopes
|
64
63
|
end
|
65
|
-
|
66
64
|
end
|
67
|
-
end
|
65
|
+
end
|
@@ -2,8 +2,7 @@ require 'ruby-swagger/object'
|
|
2
2
|
require 'ruby-swagger/data/external_documentation'
|
3
3
|
|
4
4
|
module Swagger::Data
|
5
|
-
class Tag < Swagger::Object #https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#tag-object
|
6
|
-
|
5
|
+
class Tag < Swagger::Object # https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#tag-object
|
7
6
|
attr_swagger :name, :description, :externalDocs
|
8
7
|
|
9
8
|
def self.parse(xml_object)
|
@@ -17,8 +16,7 @@ module Swagger::Data
|
|
17
16
|
|
18
17
|
newDoc = Swagger::Data::ExternalDocumentation.parse(newDoc) unless newDoc.is_a?(Swagger::Data::ExternalDocumentation)
|
19
18
|
|
20
|
-
@externalDocs=newDoc
|
19
|
+
@externalDocs = newDoc
|
21
20
|
end
|
22
|
-
|
23
21
|
end
|
24
|
-
end
|
22
|
+
end
|
@@ -1,8 +1,7 @@
|
|
1
1
|
require 'ruby-swagger/object'
|
2
2
|
|
3
3
|
module Swagger::Data
|
4
|
-
class XMLObject < Swagger::Object #https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#xmlObject
|
5
|
-
|
4
|
+
class XMLObject < Swagger::Object # https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#xmlObject
|
6
5
|
attr_swagger :name, :namespace, :prefix, :attribute, :wrapped
|
7
6
|
|
8
7
|
def self.parse(xml_object)
|
@@ -10,6 +9,5 @@ module Swagger::Data
|
|
10
9
|
|
11
10
|
Swagger::Data::XMLObject.new.bulk_set(xml_object)
|
12
11
|
end
|
13
|
-
|
14
12
|
end
|
15
|
-
end
|
13
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Swagger::Grape
|
2
|
+
class Entity
|
3
|
+
def initialize(type)
|
4
|
+
raise ArgumentError.new("Expecting a Grape::Entity - Can't translate this!") unless Object.const_get(type) < Grape::Entity
|
5
|
+
|
6
|
+
@type = type
|
7
|
+
@swagger_type = { 'type' => 'object', 'properties' => {} }
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_swagger
|
11
|
+
root_exposures.each do |exposure|
|
12
|
+
@swagger_type['properties'].merge!(Swagger::Grape::EntityExposure.new(exposure).to_swagger)
|
13
|
+
end
|
14
|
+
@swagger_type
|
15
|
+
end
|
16
|
+
|
17
|
+
def sub_types
|
18
|
+
collection = []
|
19
|
+
root_exposures.each do |exposure|
|
20
|
+
exposure = Swagger::Grape::EntityExposure.new(exposure)
|
21
|
+
collection << exposure.sub_type if exposure.sub_type
|
22
|
+
|
23
|
+
exposure.nested_exposures.each do |nested_exposure|
|
24
|
+
nested_exposure = Swagger::Grape::EntityExposure.new(nested_exposure)
|
25
|
+
collection << nested_exposure.sub_type if nested_exposure.sub_type
|
26
|
+
end if exposure.nested?
|
27
|
+
end
|
28
|
+
collection.uniq
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def root_exposures
|
34
|
+
entity_class.root_exposures
|
35
|
+
end
|
36
|
+
|
37
|
+
def entity_class
|
38
|
+
Object.const_get(@type)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Swagger::Grape
|
2
|
+
class EntityExposure
|
3
|
+
def initialize(exposure)
|
4
|
+
raise ArgumentError.new("Expecting a Grape::Entity::Exposure - Can't translate #{exposure}!") unless exposure.is_a? Grape::Entity::Exposure::Base
|
5
|
+
|
6
|
+
@exposure = exposure
|
7
|
+
@swagger_type = { attribute => {} }
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_swagger
|
11
|
+
translate
|
12
|
+
end
|
13
|
+
|
14
|
+
def sub_type
|
15
|
+
options[:using] if representer?
|
16
|
+
end
|
17
|
+
|
18
|
+
def nested?
|
19
|
+
options[:nesting] || false
|
20
|
+
end
|
21
|
+
|
22
|
+
def array?
|
23
|
+
type == 'array'
|
24
|
+
end
|
25
|
+
|
26
|
+
def representer?
|
27
|
+
@exposure.is_a? Grape::Entity::Exposure::RepresentExposure
|
28
|
+
end
|
29
|
+
|
30
|
+
def type?
|
31
|
+
type.present?
|
32
|
+
end
|
33
|
+
|
34
|
+
def nested_exposures
|
35
|
+
nested? ? @exposure.nested_exposures : nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def type
|
39
|
+
documentation[:type].to_s.downcase if documentation[:type].present?
|
40
|
+
end
|
41
|
+
|
42
|
+
def attribute
|
43
|
+
options[:as].present? ? options[:as].to_s : @exposure.attribute.to_s
|
44
|
+
end
|
45
|
+
|
46
|
+
def options
|
47
|
+
@exposure.send(:options)
|
48
|
+
rescue
|
49
|
+
{}
|
50
|
+
end
|
51
|
+
|
52
|
+
def documentation
|
53
|
+
@exposure.documentation || {}
|
54
|
+
rescue
|
55
|
+
{}
|
56
|
+
end
|
57
|
+
|
58
|
+
def description
|
59
|
+
@exposure.documentation[:desc] if @exposure.documentation[:desc].present?
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def translate
|
65
|
+
nested? ? translate_nesting_exposure : translate_exposure
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_swagger_type(property)
|
69
|
+
@swagger_type[attribute].merge!(property)
|
70
|
+
@swagger_type
|
71
|
+
end
|
72
|
+
|
73
|
+
def translate_nesting_exposure
|
74
|
+
to_swagger_type(Swagger::Grape::EntityNestingExposure.new(@exposure).to_swagger)
|
75
|
+
end
|
76
|
+
|
77
|
+
def translate_exposure
|
78
|
+
to_swagger_type(Type.new(type).to_swagger(true)) if type?
|
79
|
+
|
80
|
+
if representer?
|
81
|
+
# it's either an object or an array of object
|
82
|
+
using = Type.new(options[:using].to_s).to_swagger(true)
|
83
|
+
|
84
|
+
if array?
|
85
|
+
to_swagger_type('items' => using)
|
86
|
+
else
|
87
|
+
to_swagger_type(using)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
@swagger_type[attribute]['description'] = documentation[:desc] if documentation[:desc].present?
|
92
|
+
@swagger_type[attribute]['type'] ||= 'string' # no type defined, assuming it's a string
|
93
|
+
@swagger_type
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Swagger::Grape
|
2
|
+
class EntityNestingExposure < EntityExposure
|
3
|
+
def initialize(exposure)
|
4
|
+
raise ArgumentError.new("Expecting a NestingExposure - Can't translate #{exposure}!") unless exposure.is_a? Grape::Entity::Exposure::NestingExposure
|
5
|
+
|
6
|
+
@exposure = exposure
|
7
|
+
@properties = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_swagger
|
11
|
+
nested_exposures.each do |exposure|
|
12
|
+
@properties.merge!(Swagger::Grape::EntityExposure.new(exposure).to_swagger)
|
13
|
+
end
|
14
|
+
|
15
|
+
array? ? array_schema : object_schema
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def object_schema
|
21
|
+
{
|
22
|
+
'type' => 'object',
|
23
|
+
'properties' => @properties
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def array_schema
|
28
|
+
{
|
29
|
+
'type' => 'array',
|
30
|
+
'description' => description,
|
31
|
+
'items' => {
|
32
|
+
'type' => 'object',
|
33
|
+
'properties' => @properties
|
34
|
+
}
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,2 +1,2 @@
|
|
1
1
|
require 'ruby-swagger/grape/grape_presenter'
|
2
|
-
require 'ruby-swagger/grape/grape_config'
|
2
|
+
require 'ruby-swagger/grape/grape_config'
|
@@ -6,7 +6,6 @@ module Grape
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
module ClassMethods
|
9
|
-
|
10
9
|
def api_desc(description, options = {}, &block)
|
11
10
|
default_api_options!(options)
|
12
11
|
block.call if block_given?
|
@@ -62,27 +61,25 @@ module Grape
|
|
62
61
|
def tags(new_tags)
|
63
62
|
raise ArgumentError.new("Grape::tags - unrecognized value #{new_tags} - tags can only be an array of strings or a string") unless new_tags.is_a?(Array) || new_tags.is_a?(String)
|
64
63
|
|
65
|
-
if new_tags.is_a?(String)
|
66
|
-
new_tags = [new_tags]
|
67
|
-
end
|
64
|
+
new_tags = [new_tags] if new_tags.is_a?(String)
|
68
65
|
|
69
|
-
@api_options[:tags]= new_tags
|
66
|
+
@api_options[:tags] = new_tags
|
70
67
|
end
|
71
68
|
|
72
69
|
def response(new_result, options = {})
|
73
70
|
raise ArgumentError.new("Grape::response - response can't be nil") unless new_result
|
74
71
|
|
75
|
-
response_obj = {entity: new_result}
|
72
|
+
response_obj = { entity: new_result }
|
76
73
|
response_obj[:root] = options[:root] || options['root']
|
77
74
|
response_obj[:headers] = options[:headers] || options['headers']
|
78
75
|
response_obj[:isArray] = options[:isArray] || options['isArray']
|
79
76
|
|
80
|
-
@api_options[:response]= response_obj
|
77
|
+
@api_options[:response] = response_obj
|
81
78
|
end
|
82
79
|
|
83
80
|
def errors(errors_value)
|
84
81
|
raise ArgumentError.new("Grape::errors - unrecognized value #{errors_value} - errors root must be a hash of errors") unless errors_value.is_a?(Hash)
|
85
|
-
@api_options[:errors]= errors_value
|
82
|
+
@api_options[:errors] = errors_value
|
86
83
|
end
|
87
84
|
|
88
85
|
@@headers = {}
|
@@ -137,20 +134,20 @@ module Grape
|
|
137
134
|
|
138
135
|
def default_api_options!(options)
|
139
136
|
@api_options = {
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
137
|
+
headers: @@headers,
|
138
|
+
deprecated: @@deprecated,
|
139
|
+
hidden: @@hidden,
|
140
|
+
scopes: @@scopes,
|
141
|
+
tags: @@tags,
|
142
|
+
response: {
|
143
|
+
entity: @@response_entity,
|
144
|
+
root: @@response_root,
|
145
|
+
headers: @@response_headers,
|
146
|
+
isArray: false
|
147
|
+
},
|
148
|
+
errors: @@errors,
|
149
|
+
api_name: nil,
|
150
|
+
detail: ''
|
154
151
|
}.merge(options)
|
155
152
|
@description = ''
|
156
153
|
end
|
@@ -4,14 +4,13 @@ module Grape
|
|
4
4
|
module DSL
|
5
5
|
module InsideRoute
|
6
6
|
def api_present(*args)
|
7
|
-
|
8
7
|
args_list = args || []
|
9
8
|
options = {}
|
10
9
|
|
11
10
|
# Initialize the options hash - either by assigning to the current options for the method or with a new one
|
12
11
|
if args_list.count == 2
|
13
12
|
|
14
|
-
if args_list.last.
|
13
|
+
if args_list.last.is_a?(Hash)
|
15
14
|
options = args_list.last
|
16
15
|
else
|
17
16
|
raise ArgumentError.new "The expected second argument for api_present is a Hash, but I got a #{args_list.last.class}"
|
@@ -19,7 +18,7 @@ module Grape
|
|
19
18
|
|
20
19
|
elsif args_list.count == 1
|
21
20
|
|
22
|
-
#Initialize the option list
|
21
|
+
# Initialize the option list
|
23
22
|
args_list << options
|
24
23
|
|
25
24
|
elsif args_list.count > 2 || args_list.count == 0
|
@@ -27,21 +26,19 @@ module Grape
|
|
27
26
|
end
|
28
27
|
|
29
28
|
# Setting the grape :with
|
30
|
-
if route.route_response.present? && route.route_response[:entity].present?
|
29
|
+
if route.route_response.present? && route.route_response[:entity].present? && !options[:with].present? && route.route_response[:entity].is_a?(Class)
|
31
30
|
options[:with] = route.route_response[:entity]
|
32
31
|
end
|
33
32
|
|
34
33
|
# Setting the grape :root
|
35
|
-
if route.route_response.present? && route.route_response[:root].present? && !options[:root].present? && route.route_response[:root].
|
34
|
+
if route.route_response.present? && route.route_response[:root].present? && !options[:root].present? && route.route_response[:root].is_a?(String)
|
36
35
|
options[:root] = route.route_response[:root]
|
37
36
|
end
|
38
37
|
|
39
38
|
# Setting the :current_user extension
|
40
|
-
if defined?(current_user)
|
41
|
-
options[:current_user] = current_user
|
42
|
-
end
|
39
|
+
options[:current_user] = current_user if defined?(current_user)
|
43
40
|
|
44
|
-
present
|
41
|
+
present(*args_list)
|
45
42
|
end
|
46
43
|
end
|
47
44
|
end
|