diff --git a/src/SDK/Language/Ruby.php b/src/SDK/Language/Ruby.php index e84e34f85..87368ae36 100644 --- a/src/SDK/Language/Ruby.php +++ b/src/SDK/Language/Ruby.php @@ -193,10 +193,6 @@ public function getTypeName($type) case self::TYPE_INTEGER: case self::TYPE_NUMBER: return 'number'; - break; - case self::TYPE_FILE: - return 'File'; - break; } return $type; diff --git a/templates/ruby/lib/container/client.rb.twig b/templates/ruby/lib/container/client.rb.twig index 0f89376bf..bc7c6d3b6 100644 --- a/templates/ruby/lib/container/client.rb.twig +++ b/templates/ruby/lib/container/client.rb.twig @@ -9,6 +9,7 @@ module {{ spec.title | caseUcfirst }} class Client def initialize + @chunk_size = 5*1024*1024 @headers = { 'user-agent' => RUBY_PLATFORM + ':{{ language.name | caseLower }}-' + RUBY_VERSION, 'x-sdk-version' => '{{ spec.title | caseDash }}:{{ language.name | caseLower }}:{{ sdk.version }}'{% if spec.global.defaultHeaders | length > 0 %},{% endif %} @@ -94,6 +95,61 @@ module {{ spec.title | caseUcfirst }} fetch(method, uri, headers, params, response_type) end + def chunked_upload( + path:, + headers:, + params:, + param_name: '', + on_progress: nil, + response_type: nil + ) + file_path = params[param_name.to_sym] + size = ::File.size(file_path) + + if size < @chunk_size + slice = ::File.read(file_path) + params[param_name] = File.new(file_path, slice) + return call( + method: 'POST', + path: path, + headers: headers, + params: params, + response_type: response_type, + ) + end + + input = ::File.open(file_path) + offset = 0 + + while offset < size + slice = input.read(@chunk_size) + + params[param_name] = File.new(file_path, slice) + headers['content-range'] = "bytes #{offset}-#{[offset + @chunk_size - 1, size].min}/#{size}" + + result = call( + method: 'POST', + path: path, + headers: headers, + params: params, + ) + + offset += @chunk_size + + if defined? result['$id'] + headers['x-{{ spec.title }}-id'] = result['$id'] + end + + unless on_progress.nil? + on_progress(min(offset, size)/size * 100) + end + end + + return result unless response_type.respond_to?("from") + + response_type.from(map: result) + end + private def fetch( @@ -147,7 +203,7 @@ module {{ spec.title | caseUcfirst }} end if response.code.to_i >= 400 - raise Appwrite::Exception.new(result['message'], result['status'], result) + raise {{spec.title | caseUcfirst}}::Exception.new(result['message'], result['status'], result) end unless response_type.respond_to?("from") @@ -158,7 +214,7 @@ module {{ spec.title | caseUcfirst }} end if response.code.to_i >= 400 - raise Appwrite::Exception.new(response.body, response.code, response) + raise {{spec.title | caseUcfirst}}::Exception.new(response.body, response.code, response) end return response.body if response.body_permitted? diff --git a/templates/ruby/lib/container/file.rb.twig b/templates/ruby/lib/container/file.rb.twig index 98be8081d..1ad7d2fa1 100644 --- a/templates/ruby/lib/container/file.rb.twig +++ b/templates/ruby/lib/container/file.rb.twig @@ -2,13 +2,15 @@ require 'mime/types' module {{spec.title | caseUcfirst}} class File + attr_reader :path attr_reader :name attr_reader :content attr_reader :mime_type - def initialize(path) + def initialize(path, content) + @path = path + @content = content @name = ::File.basename(path) - @content = ::File.read(path) @mime_type = MIME::Types.type_for(path) end end diff --git a/templates/ruby/lib/container/services/service.rb.twig b/templates/ruby/lib/container/services/service.rb.twig index 4fe347f72..15a2ffdf4 100644 --- a/templates/ruby/lib/container/services/service.rb.twig +++ b/templates/ruby/lib/container/services/service.rb.twig @@ -12,7 +12,7 @@ module {{spec.title | caseUcfirst}} {% endfor %} # # @return [{{ method.responseModel | caseUcfirst }}] - def {{ method.name | caseSnake }}({% for parameter in method.parameters.all %}{{ parameter.name | caseSnake | escapeKeyword }}:{% if not parameter.required %} nil{% endif %}{% if not loop.last %}, {% endif %}{% endfor %}) + def {{ method.name | caseSnake }}({% for parameter in method.parameters.all %}{{ parameter.name | caseSnake | escapeKeyword }}:{% if not parameter.required %} nil{% endif %}{% if not loop.last %}, {% endif %}{% endfor %}{% if 'multipart/form-data' in method.consumes %}, on_progress: nil{% endif %}) {% for parameter in method.parameters.all %} {% if parameter.required %} if {{ parameter.name | caseSnake | escapeKeyword }}.nil? @@ -41,15 +41,34 @@ module {{spec.title | caseUcfirst}} {% endfor %} } +{% if 'multipart/form-data' in method.consumes %} +{% for parameter in method.parameters.all %} +{% if parameter.type == 'file' %} + param_name = '{{ parameter.name }}' + +{% endif %} +{% endfor %} + @client.chunked_upload( + path: path, + headers: headers, + params: params, + param_name: param_name, + on_progress: on_progress, +{% if method.responseModel and method.responseModel != 'any' %} + response_type: {{method.responseModel | caseUcfirst}} +{% endif %} + ) +{% else %} @client.call( method: '{{ method.method | caseUpper }}', path: path, - params: params, headers: headers, + params: params, {% if method.responseModel and method.responseModel != 'any' %} response_type: {{method.responseModel | caseUcfirst}} {% endif %} ) +{% endif %} end {% endfor %} diff --git a/tests/SDKTest.php b/tests/SDKTest.php index 4a47cf7ec..66495ff68 100644 --- a/tests/SDKTest.php +++ b/tests/SDKTest.php @@ -270,16 +270,18 @@ class SDKTest extends TestCase 'ruby' => [ 'class' => 'Appwrite\SDK\Language\Ruby', 'build' => [ - 'docker run --rm -v $(pwd):/app -w /app/tests/sdks/ruby --env GEM_HOME=/app/vendor ruby:2.7-alpine sh -c "apk add git build-base && bundle install"', + 'docker run --rm -v $(pwd):/app -w /app/tests/sdks/ruby --env GEM_HOME=/app/vendor ruby:3.1-alpine sh -c "apk add git build-base && bundle install"', ], 'envs' => [ - 'ruby-2.7' => 'docker run --rm -v $(pwd):/app -w /app --env GEM_HOME=vendor ruby:2.7-alpine ruby tests/languages/ruby/tests.rb', + 'ruby-3.1' => 'docker run --rm -v $(pwd):/app -w /app --env GEM_HOME=vendor ruby:3.1-alpine ruby tests/languages/ruby/tests.rb', 'ruby-3.0' => 'docker run --rm -v $(pwd):/app -w /app --env GEM_HOME=vendor ruby:3.0-alpine ruby tests/languages/ruby/tests.rb', + 'ruby-2.7' => 'docker run --rm -v $(pwd):/app -w /app --env GEM_HOME=vendor ruby:2.7-alpine ruby tests/languages/ruby/tests.rb', ], 'expectedOutput' => [ ...FOO_RESPONSES, ...BAR_RESPONSES, ...GENERAL_RESPONSES, + 'POST:/v1/mock/tests/general/upload:passed', ...EXCEPTION_RESPONSES, ], ], diff --git a/tests/languages/ruby/tests.rb b/tests/languages/ruby/tests.rb index b980bf94a..1e90f650f 100644 --- a/tests/languages/ruby/tests.rb +++ b/tests/languages/ruby/tests.rb @@ -49,8 +49,10 @@ response = general.redirect() puts response["result"] -file = Appwrite::File.new('./tests/resources/file.png') -response = general.upload(x: 'string', y: 123, z:['string in array'], file: file) +response = general.upload(x: 'string', y: 123, z:['string in array'], file: './tests/resources/file.png') +puts response.result + +response = general.upload(x: 'string', y: 123, z:['string in array'], file: './tests/resources/large_file.mp4') puts response.result begin diff --git a/tests/resources/large_file.mp4 b/tests/resources/large_file.mp4 new file mode 100644 index 000000000..5a275ab90 Binary files /dev/null and b/tests/resources/large_file.mp4 differ