Skip to content

Commit 8f8a013

Browse files
Merge pull request #301 from appwrite/feat-ruby-response-models
Feat ruby response models
2 parents f5a621c + 86ddd58 commit 8f8a013

File tree

14 files changed

+284
-147
lines changed

14 files changed

+284
-147
lines changed

src/SDK/Language/Ruby.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@ public function getFiles()
160160
'template' => 'ruby/.travis.yml.twig',
161161
'minify' => false,
162162
],
163+
[
164+
'scope' => 'definition',
165+
'destination' => '/lib/{{ spec.title | caseDash }}/models/{{ definition.name | caseSnake }}.rb',
166+
'template' => 'ruby/lib/container/models/model.rb.twig',
167+
'minify' => false,
168+
],
163169
];
164170
}
165171

src/SDK/SDK.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,13 @@ public function __construct(Language $language, Spec $spec)
167167
}
168168
return implode("\n", $value);
169169
}, ['is_safe' => ['html']]));
170+
$this->twig->addFilter(new TwigFilter('rubyComment', function ($value) {
171+
$value = explode("\n", $value);
172+
foreach ($value as $key => $line) {
173+
$value[$key] = " # " . wordwrap($line, 75, "\n # ");
174+
}
175+
return implode("\n", $value);
176+
}, ['is_safe' => ['html']]));
170177
$this->twig->addFilter(new TwigFilter('escapeDollarSign', function ($value) {
171178
return str_replace('$', '\$', $value);
172179
}, ['is_safe'=>['html']]));

templates/ruby/Gemfile.twig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
source 'https://rubygems.org'
22

3-
gem 'mime-types', '~> 3.3.1'
43
gemspec
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
require 'appwrite'
22

3-
client = Appwrite::Client.new()
3+
client = Appwrite::Client.new
44

55
client
66
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
77
{% for node in method.security %}
88
{% for key,header in node|keys %}
99
.set_{{header|caseSnake}}('{{node[header]['x-appwrite']['demo']}}') # {{node[header].description}}
1010
{% endfor %}
11-
{% endfor %};
11+
{% endfor %}
1212

13-
{{ service.name | caseSnake }} = {{spec.title | caseUcfirst}}::{{ service.name | caseUcfirst }}.new(client);
13+
{{ service.name | caseSnake }} = {{spec.title | caseUcfirst}}::{{ service.name | caseUcfirst }}.new(client)
1414

15-
response = {{ service.name | caseSnake }}.{{ method.name | caseSnake }}({% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %}, {% endif %}{{parameter.name|caseSnake}}: {% if parameter | paramExample == "File.new()" %}{{spec.title | caseUcfirst}}::{{ parameter | paramExample }}{% else %}{{ parameter | paramExample }}{% endif %}{% endif %}{% endfor %});
15+
response = {{ service.name | caseSnake }}.{{ method.name | caseSnake }}({% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %}, {% endif %}{{parameter.name|caseSnake}}: {% if parameter | paramExample == "File.new" %}{{spec.title | caseUcfirst}}::{{ parameter | paramExample }}{% else %}{{ parameter | paramExample }}{% endif %}{% endif %}{% endfor %})
1616

17-
puts response
17+
puts response.inspect

templates/ruby/gemspec.twig

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
Gem::Specification.new do |s|
2-
3-
s.name = '{{spec.title | caseLower | caseSnake}}'
4-
s.version = '{{ sdk.version }}'
5-
s.summary = "{{ sdk.shortDescription }}"
6-
s.author = '{{ spec.contactName }}'
7-
s.homepage = '{{ spec.contactURL }}'
8-
s.email = '{{ spec.contactEmail }}'
9-
s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
10-
1+
Gem::Specification.new do |spec|
2+
3+
spec.name = '{{spec.title | caseLower | caseSnake}}'
4+
spec.version = '{{ sdk.version }}'
5+
spec.license = '{{ spec.licenseName }}'
6+
spec.summary = '{{ sdk.shortDescription }}'
7+
spec.author = '{{ spec.contactName }}'
8+
spec.homepage = '{{ spec.contactURL }}'
9+
spec.email = '{{ spec.contactEmail }}'
10+
spec.files = Dir['lib/**/*.rb']
11+
12+
spec.add_dependency 'mime-types', '~> 3.3.1'
1113
end

templates/ruby/lib/container.rb.twig

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@ require 'net/http'
22
require 'uri'
33
require 'json'
44
require 'mime/types'
5-
require_relative '{{ spec.title | caseDash }}/client'
6-
require_relative '{{ spec.title | caseDash }}/service'
7-
require_relative '{{ spec.title | caseDash }}/exception'
8-
require_relative '{{ spec.title | caseDash }}/file'
5+
6+
require_relative '{{ spec.title | caseSnake }}/client'
7+
require_relative '{{ spec.title | caseSnake }}/service'
8+
require_relative '{{ spec.title | caseSnake }}/exception'
9+
require_relative '{{ spec.title | caseSnake }}/file'
10+
11+
{% for defintion in spec.definitions %}
12+
require_relative '{{ spec.title | caseSnake }}/models/{{ defintion.name | caseSnake }}'
13+
{% endfor %}
14+
915
{% for service in spec.services %}
10-
require_relative '{{ spec.title | caseDash }}/services/{{ service.name | caseDash }}'
16+
require_relative '{{ spec.title | caseSnake }}/services/{{ service.name | caseSnake }}'
1117
{% endfor %}
Lines changed: 106 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,15 @@
1+
#frozen_string_literal: true
2+
13
require 'net/http'
24
require 'uri'
35
require 'json'
46
require 'cgi'
57

6-
module {{spec.title | caseUcfirst}}
8+
module {{ spec.title | caseUcfirst }}
79
class Client
8-
9-
METHOD_GET = 'get'
10-
METHOD_POST = 'post'
11-
METHOD_PUT = 'put'
12-
METHOD_PATCH = 'patch'
13-
METHOD_DELETE = 'delete'
14-
METHOD_HEAD = 'head'
15-
METHOD_OPTIONS = 'options'
16-
METHOD_CONNECT = 'connect'
17-
METHOD_TRACE = 'trace'
18-
19-
def initialize()
10+
11+
def initialize
2012
@headers = {
21-
'content-type' => '',
2213
'user-agent' => RUBY_PLATFORM + ':{{ language.name | caseLower }}-' + RUBY_VERSION,
2314
'x-sdk-version' => '{{ spec.title | caseDash }}:{{ language.name | caseLower }}:{{ sdk.version }}'{% if spec.global.defaultHeaders | length > 0 %},{% endif %}
2415

@@ -27,110 +18,171 @@ module {{spec.title | caseUcfirst}}
2718
{% endfor %}
2819

2920
}
30-
@endpoint = '{{spec.endpoint}}';
21+
@endpoint = '{{spec.endpoint}}'
3122
end
3223

3324
{% for header in spec.global.headers %}
25+
# Set {{header.key | caseUcfirst}}
26+
#
27+
{% if header.description %}
28+
# {{header.description}}
29+
#
30+
{% endif %}
31+
# @param [String] value The value to set for the {{ header.key }} header
32+
#
33+
# @return [self]
3434
def set_{{header.key | caseSnake}}(value)
3535
add_header('{{header.name | caseLower}}', value)
3636

37-
return self
37+
self
3838
end
3939

4040
{% endfor %}
41+
# Set endpoint.
42+
#
43+
# @param [String] endpoint The endpoint to set
44+
#
45+
# @return [self]
4146
def set_endpoint(endpoint)
4247
@endpoint = endpoint
4348

44-
return self
49+
self
4550
end
46-
51+
52+
# Set self signed.
53+
#
54+
# @param [String] self_signed Whether to allow self signed certificates.
55+
#
56+
# @return [self]
57+
def set_self_signed(self_signed = true)
58+
@self_signed = self_signed
59+
60+
self
61+
end
62+
63+
64+
# Add Header
65+
#
66+
# @param [String] key The key for the header to add
67+
# @param [String] value The value for the header to add
68+
#
69+
# @return [self]
4770
def add_header(key, value)
4871
@headers[key.downcase] = value
4972

50-
return self
51-
end
52-
53-
def call(method, path = '', headers = {}, params = {})
54-
uri = URI.parse(@endpoint + path + ((method == METHOD_GET && params.length) ? '?' + encode(params) : ''))
55-
return fetch(method, uri, headers, params)
73+
self
5674
end
5775

58-
protected
76+
# Send the HTTP request.
77+
#
78+
# @param [String] method The HTTP method for the request
79+
# @param [String] path The path for the request
80+
# @param [Hash] headers The headers to send with the request
81+
# @param [Hash] params The parameters to send with the request
82+
# @param [Class] response_type The type of response to return
83+
#
84+
# @return [self]
85+
def call(
86+
method:,
87+
path: '',
88+
headers: {},
89+
params: {},
90+
response_type: nil
91+
)
92+
uri = URI.parse(@endpoint + path + ((method == "GET" && params.length) ? '?' + encode(params) : ''))
93+
94+
fetch(method, uri, headers, params, response_type)
95+
end
5996

6097
private
6198

62-
def fetch(method, uri, headers, params, limit = 5)
99+
def fetch(
100+
method,
101+
uri,
102+
headers,
103+
params,
104+
response_type = nil,
105+
limit = 5
106+
)
63107
raise ArgumentError, 'Too Many HTTP Redirects' if limit == 0
64108

65-
http = Net::HTTP.new(uri.host, uri.port)
66-
http.use_ssl = (uri.scheme == 'https')
109+
@http = Net::HTTP.new(uri.host, uri.port) unless defined? @http
110+
@http.use_ssl = !@self_signed
67111
payload = ''
68112

69113
headers = @headers.merge(headers)
70-
@BOUNDARY = "----A30#3ad1"
71-
if (method != METHOD_GET)
72-
case headers['content-type'][0, headers['content-type'].index(';') || headers['content-type'].length]
114+
115+
@boundary = "----A30#3ad1"
116+
if method != "GET"
117+
case headers[:'content-type']
73118
when 'application/json'
74119
payload = params.to_json
75120
when 'multipart/form-data'
76-
payload = "--#{@BOUNDARY}\r\n" + encodeFormData(params)
77-
headers['content-type'] = "multipart/form-data; boundary=#{@BOUNDARY}"
121+
payload = "--#{@boundary}\r\n" + encode_form_data(params)
122+
headers[:'content-type'] = "multipart/form-data; boundary=#{@boundary}"
78123
else
79124
payload = encode(params)
80125
end
81126
end
82127

83128
begin
84-
response = http.send_request(method.upcase, uri.request_uri, payload, headers)
129+
response = @http.send_request(method, uri.request_uri, payload, headers)
85130
rescue => error
86131
raise {{spec.title | caseUcfirst}}::Exception.new(error.message)
87132
end
88133

89134
# Handle Redirects
90-
if (response.class == Net::HTTPRedirection || response.class == Net::HTTPMovedPermanently)
135+
if response.class == Net::HTTPRedirection || response.class == Net::HTTPMovedPermanently
91136
location = response['location']
92137
uri = URI.parse(uri.scheme + "://" + uri.host + "" + location)
93138

94-
return fetch(method, uri, headers, {}, limit - 1)
139+
return fetch(method, uri, headers, {}, response_type, limit - 1)
95140
end
96141

97142
if response.content_type == 'application/json'
98143
begin
99-
json = JSON.parse(response.body)
100-
101-
if response.class == Net::HTTPClientError || response.class == Net::HTTPServerError
102-
raise {{spec.title | caseUcfirst}}::Exception.new(json['message'], json['status'], response)
103-
end
144+
result = JSON.parse(response.body)
104145
rescue JSON::ParserError => e
105-
raise {{spec.title | caseUcfirst}}::Exception.new(e.message, response.code, response)
146+
raise {{spec.title | caseUcfirst}}::Exception.new(response.body, response.code, response)
106147
end
107148

108-
return json
149+
if response.code.to_i >= 400
150+
raise Appwrite::Exception.new(result['message'], result['status'], result)
151+
end
152+
153+
unless response_type.respond_to?("from")
154+
return result
155+
end
156+
157+
return response_type.from(map: result)
109158
end
110159

111-
if response.class == Net::HTTPClientError || response.class == Net::HTTPServerError
112-
raise {{spec.title | caseUcfirst}}::Exception.new(response.body, response.code, response)
160+
if response.code.to_i >= 400
161+
raise Appwrite::Exception.new(response.body, response.code, response)
113162
end
114163

115164
return response.body if response.body_permitted?
116165
end
117166

118-
def encodeFormData(value, key=nil)
167+
def encode_form_data(value, key=nil)
119168
case value
120-
when Hash then value.map { |k,v| encodeFormData(v,k) }.join
121-
when Array then value.map { |v| encodeFormData(v, "#{key}[]") }.join
122-
when nil then ''
169+
when Hash
170+
value.map { |k,v| encode_form_data(v,k) }.join
171+
when Array
172+
value.map { |v| encode_form_data(v, "#{key}[]") }.join
173+
when nil
174+
''
123175
else
124176
post_body = []
125-
if(value.instance_of? File)
177+
if value.instance_of? File
126178
post_body << "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{value.name}\"\r\n"
127-
post_body << "Content-Type: #{value.mimeType}\r\n\r\n"
179+
post_body << "Content-Type: #{value.mime_type}\r\n\r\n"
128180
post_body << value.content
129-
post_body << "\r\n--#{@BOUNDARY}--\r\n"
181+
post_body << "\r\n--#{@boundary}--\r\n"
130182
else
131183
post_body << "Content-Disposition: form-data; name=\"#{key}\"\r\n\r\n"
132184
post_body << "#{value.to_s}"
133-
post_body << "\r\n--#{@BOUNDARY}\r\n"
185+
post_body << "\r\n--#{@boundary}\r\n"
134186
end
135187
post_body.join
136188
end
@@ -150,4 +202,4 @@ module {{spec.title | caseUcfirst}}
150202
root_key.nil? ? key : "#{root_key}[#{key.to_s}]"
151203
end
152204
end
153-
end
205+
end
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
module Appwrite
22
class Exception < StandardError
3-
@code = 0;
4-
@response = nil;
3+
attr_reader :code
4+
attr_reader :response
55

6-
def initialize(message, code, response)
6+
def initialize(message, code = 0, response = nil)
77
super(message)
88
@code = code
99
@response = response
1010
end
11-
attr_reader :code
12-
attr_reader :response
1311
end
1412
end

0 commit comments

Comments
 (0)