uploadcare-ruby 2.1.1 → 3.1.0.pre.rc1

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 (116) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/gem-push.yml +20 -0
  3. data/.github/workflows/ruby.yml +52 -0
  4. data/.gitignore +13 -6
  5. data/.rspec +2 -0
  6. data/.rubocop.yml +32 -0
  7. data/.yardopts +4 -0
  8. data/CHANGELOG.md +33 -34
  9. data/DEVELOPMENT.md +18 -0
  10. data/Gemfile +2 -0
  11. data/LICENSE +1 -1
  12. data/README.md +369 -546
  13. data/Rakefile +5 -5
  14. data/bin/console +15 -0
  15. data/bin/setup +8 -0
  16. data/lib/uploadcare.rb +36 -26
  17. data/lib/uploadcare/api/api.rb +25 -0
  18. data/lib/uploadcare/client/conversion/base_conversion_client.rb +54 -0
  19. data/lib/uploadcare/client/conversion/document_conversion_client.rb +38 -0
  20. data/lib/uploadcare/client/conversion/video_conversion_client.rb +42 -0
  21. data/lib/uploadcare/client/file_client.rb +44 -0
  22. data/lib/uploadcare/client/file_list_client.rb +46 -0
  23. data/lib/uploadcare/client/group_client.rb +45 -0
  24. data/lib/uploadcare/client/multipart_upload/chunks_client.rb +48 -0
  25. data/lib/uploadcare/client/multipart_upload_client.rb +67 -0
  26. data/lib/uploadcare/client/project_client.rb +18 -0
  27. data/lib/uploadcare/client/rest_client.rb +74 -0
  28. data/lib/uploadcare/client/rest_group_client.rb +23 -0
  29. data/lib/uploadcare/client/upload_client.rb +36 -0
  30. data/lib/uploadcare/client/uploader_client.rb +109 -0
  31. data/lib/uploadcare/client/webhook_client.rb +47 -0
  32. data/lib/uploadcare/concern/error_handler.rb +54 -0
  33. data/lib/uploadcare/concern/throttle_handler.rb +25 -0
  34. data/lib/uploadcare/concern/upload_error_handler.rb +32 -0
  35. data/lib/uploadcare/entity/decorator/paginator.rb +79 -0
  36. data/lib/uploadcare/entity/document_converter.rb +26 -0
  37. data/lib/uploadcare/entity/entity.rb +18 -0
  38. data/lib/uploadcare/entity/file.rb +81 -0
  39. data/lib/uploadcare/entity/file_list.rb +31 -0
  40. data/lib/uploadcare/entity/group.rb +40 -0
  41. data/lib/uploadcare/entity/group_list.rb +24 -0
  42. data/lib/uploadcare/entity/project.rb +13 -0
  43. data/lib/uploadcare/entity/uploader.rb +75 -0
  44. data/lib/uploadcare/entity/video_converter.rb +26 -0
  45. data/lib/uploadcare/entity/webhook.rb +14 -0
  46. data/lib/uploadcare/exception/conversion_error.rb +8 -0
  47. data/lib/uploadcare/exception/request_error.rb +9 -0
  48. data/lib/uploadcare/exception/throttle_error.rb +16 -0
  49. data/lib/uploadcare/param/authentication_header.rb +25 -0
  50. data/lib/uploadcare/param/conversion/document/processing_job_url_builder.rb +39 -0
  51. data/lib/uploadcare/param/conversion/video/processing_job_url_builder.rb +64 -0
  52. data/lib/uploadcare/param/param.rb +10 -0
  53. data/lib/uploadcare/param/secure_auth_header.rb +37 -0
  54. data/lib/uploadcare/param/simple_auth_header.rb +14 -0
  55. data/lib/uploadcare/param/upload/signature_generator.rb +24 -0
  56. data/lib/uploadcare/param/upload/upload_params_generator.rb +23 -0
  57. data/lib/uploadcare/param/user_agent.rb +21 -0
  58. data/lib/uploadcare/ruby/version.rb +5 -0
  59. data/uploadcare-ruby.gemspec +50 -37
  60. metadata +109 -115
  61. data/.travis.yml +0 -26
  62. data/UPGRADE_NOTES.md +0 -36
  63. data/lib/uploadcare/api.rb +0 -26
  64. data/lib/uploadcare/api/file_api.rb +0 -7
  65. data/lib/uploadcare/api/file_list_api.rb +0 -19
  66. data/lib/uploadcare/api/file_storage_api.rb +0 -34
  67. data/lib/uploadcare/api/group_api.rb +0 -38
  68. data/lib/uploadcare/api/group_list_api.rb +0 -17
  69. data/lib/uploadcare/api/project_api.rb +0 -9
  70. data/lib/uploadcare/api/raw_api.rb +0 -38
  71. data/lib/uploadcare/api/uploading_api.rb +0 -71
  72. data/lib/uploadcare/api/uploading_api/upload_params.rb +0 -72
  73. data/lib/uploadcare/api/validators/file_list_options_validator.rb +0 -73
  74. data/lib/uploadcare/api/validators/group_list_options_validator.rb +0 -49
  75. data/lib/uploadcare/errors/errors.rb +0 -64
  76. data/lib/uploadcare/resources/file.rb +0 -164
  77. data/lib/uploadcare/resources/file_list.rb +0 -14
  78. data/lib/uploadcare/resources/group.rb +0 -115
  79. data/lib/uploadcare/resources/group_list.rb +0 -14
  80. data/lib/uploadcare/resources/project.rb +0 -13
  81. data/lib/uploadcare/resources/resource_list.rb +0 -83
  82. data/lib/uploadcare/rest/auth/auth.rb +0 -31
  83. data/lib/uploadcare/rest/auth/secure.rb +0 -43
  84. data/lib/uploadcare/rest/auth/simple.rb +0 -16
  85. data/lib/uploadcare/rest/connections/api_connection.rb +0 -53
  86. data/lib/uploadcare/rest/connections/upload_connection.rb +0 -22
  87. data/lib/uploadcare/rest/middlewares/auth_middleware.rb +0 -24
  88. data/lib/uploadcare/rest/middlewares/parse_json_middleware.rb +0 -33
  89. data/lib/uploadcare/rest/middlewares/raise_error_middleware.rb +0 -21
  90. data/lib/uploadcare/utils/parser.rb +0 -71
  91. data/lib/uploadcare/utils/user_agent.rb +0 -44
  92. data/lib/uploadcare/version.rb +0 -3
  93. data/spec/api/file_list_api_spec.rb +0 -95
  94. data/spec/api/file_storage_api_spec.rb +0 -88
  95. data/spec/api/group_list_api_spec.rb +0 -59
  96. data/spec/api/raw_api_spec.rb +0 -25
  97. data/spec/api/uploading_api/upload_params_spec.rb +0 -99
  98. data/spec/api/uploading_api_spec.rb +0 -59
  99. data/spec/resources/file_list_spec.rb +0 -25
  100. data/spec/resources/file_spec.rb +0 -223
  101. data/spec/resources/group_list_spec.rb +0 -25
  102. data/spec/resources/group_spec.rb +0 -101
  103. data/spec/resources/operations_spec.rb +0 -59
  104. data/spec/resources/project_spec.rb +0 -21
  105. data/spec/rest/api_connection_spec.rb +0 -68
  106. data/spec/rest/auth/secure_spec.rb +0 -66
  107. data/spec/rest/auth/simple_spec.rb +0 -31
  108. data/spec/rest/errors_spec.rb +0 -75
  109. data/spec/rest/upload_connection_spec.rb +0 -19
  110. data/spec/shared/resource_list.rb +0 -188
  111. data/spec/spec_helper.rb +0 -54
  112. data/spec/uploadcare_spec.rb +0 -16
  113. data/spec/utils/parser_spec.rb +0 -85
  114. data/spec/utils/user_agent_spec.rb +0 -46
  115. data/spec/view.png +0 -0
  116. data/spec/view2.jpg +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a91d6bc58cb4485cc93ff080fa5f66040b6ab0f0
4
- data.tar.gz: ae95eb7e6d60828a91883c1c481e7a469d49702a
2
+ SHA256:
3
+ metadata.gz: b37d6357bdceca37eb0175201e52847b253c701771e3bed959e7e945e4b384b7
4
+ data.tar.gz: c70b33bed6660c649df6e93a5bb7e8b3cb5a4c79884a7c146086f0658da690a3
5
5
  SHA512:
6
- metadata.gz: e3b503ac19459939ec38af251f322c3804dec77546deeeba3d192757927a2cf4eef04d4f2b2ac2265efc42e42233f54d0f2fe66d2dcd29ced6ab18c65f6432c8
7
- data.tar.gz: c08f3fb47d507b520c0859ee268ce8926b014fa7895b3a288f881586e857724a825f075899827f07a02c33228c790a26848728294cd5b8add0e323c14c49502f
6
+ metadata.gz: 47b8ead48824c45759a89a62e170374afe3cc0e8a39690ba4851c04785ee52096769a4415fea2e7ecffb62a864a5fae5f6fb1e95bf450442141973b0412990e7
7
+ data.tar.gz: a7aa262e0982825592487187f99018f5276582dffbfa3ef412abc06a3c9d723906d64d2443c79c20eb0dce137ae1cec4384c40b54e692170915289c8191032b0
@@ -0,0 +1,20 @@
1
+ name: Publish Gem
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - v*
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-latest
10
+
11
+ steps:
12
+ - uses: actions/checkout@v1
13
+
14
+ - name: Release Gem
15
+ if: contains(github.ref, 'refs/tags/v')
16
+ uses: cadwallion/publish-rubygems-action@v1.0.0
17
+ env:
18
+ GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
19
+ RUBYGEMS_API_KEY: ${{secrets.RUBYGEMS_API_KEY}}
20
+ RELEASE_COMMAND: rake release
@@ -0,0 +1,52 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Ruby
9
+
10
+ on: [push, pull_request]
11
+
12
+ jobs:
13
+ test:
14
+
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ matrix:
18
+ ruby-version: [
19
+ '2.4', '2.5', # eol
20
+ '2.6', '2.7', # maintained
21
+ ]
22
+
23
+ steps:
24
+ - uses: actions/checkout@v2
25
+ - name: Set up Ruby
26
+ uses: ruby/setup-ruby@v1
27
+ with:
28
+ ruby-version: ${{ matrix.ruby-version }}
29
+ bundler-cache: true
30
+ - name: Run tests
31
+ run: bundle exec rake
32
+ env:
33
+ UPLOADCARE_PUBLIC_KEY: demopublickey
34
+ UPLOADCARE_SECRET_KEY: demoprivatekey
35
+
36
+ style-check:
37
+ runs-on: ubuntu-latest
38
+ continue-on-error: true
39
+ strategy:
40
+ matrix:
41
+ ruby-version: ['2.7',]
42
+ steps:
43
+ - uses: actions/checkout@v2
44
+ - name: Set up Ruby
45
+ uses: ruby/setup-ruby@v1
46
+ with:
47
+ ruby-version: ${{ matrix.ruby-version }}
48
+ bundler-cache: true
49
+ - name: Install Rubocop
50
+ run: gem install rubocop
51
+ - name: Check codestyle
52
+ run: rubocop
data/.gitignore CHANGED
@@ -1,7 +1,14 @@
1
- Gemfile.lock
2
- .ruby-gemset
3
- .ruby-version
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /spec/fixtures/big.jpeg
4
10
 
5
- *.DS_Store
6
- *.gem
7
- coverage
11
+ # rspec failure tracking
12
+ .rspec_status
13
+ .byebug_history
14
+ Gemfile.lock
data/.rspec CHANGED
@@ -1 +1,3 @@
1
+ --format documentation
1
2
  --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,32 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.7
3
+
4
+ Metrics/LineLength:
5
+ Max: 120
6
+
7
+ IneffectiveAccessModifier:
8
+ Enabled: false
9
+
10
+ Style/HashTransformKeys:
11
+ Exclude:
12
+ - 'lib/uploadcare/entity/decorator/paginator.rb'
13
+ - 'lib/uploadcare/client/conversion/video_conversion_client.rb'
14
+
15
+ Gemspec/RequiredRubyVersion:
16
+ Exclude:
17
+ - 'uploadcare-ruby.gemspec'
18
+
19
+ Metrics/BlockLength:
20
+ Exclude:
21
+ - 'bin/'
22
+ - 'spec/**/*'
23
+ - 'uploadcare-ruby.gemspec'
24
+
25
+ Metrics/MethodLength:
26
+ Max: 20
27
+
28
+ Style/Documentation:
29
+ Enabled: false
30
+
31
+ Style/OptionalBooleanParameter:
32
+ AllowedMethods: ['create']
data/.yardopts ADDED
@@ -0,0 +1,4 @@
1
+ -
2
+ DEVELOPMENT.md
3
+ CHANGELOG.md
4
+ LICENSE
data/CHANGELOG.md CHANGED
@@ -1,54 +1,53 @@
1
1
  # Changelog
2
- All notable changes to this project will be documented in this file.
3
2
 
4
- The format is based now on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
- and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
3
+ ## 3.1.0-rc1 2021-08-11
6
4
 
7
- ## [Unreleased] - FIXME
5
+ ### Added
6
+ - Add video conversion
7
+ - Add document conversion
8
+ - Add new attributes to Uploadcare::File (variations, video_info, source, rekognition_info)
8
9
 
10
+ ### Fixed
9
11
 
10
- ## [2.1.1] - 2018-05-24
12
+ - Fix the `uninitialized constant Uploadcare::Client::ApiStruct (NameError)` error
11
13
 
12
- ### Changed
13
- - Allow user to override User-Agent header
14
- - User-Agent format reports gem name, version and environment
14
+ ## 3.0.5 2021-04-15
15
15
 
16
- ## 2.1.0 - 2018-04-23 [YANKED]
16
+ - Replace Travis-CI with Github Actions
17
+ - Automate gem pushing
17
18
 
18
- ## 2.0.0 - 2017-09-26
19
+ ## 3.0.4-dev 2020-03-19
19
20
 
20
- There are **breaking** changes in this release, please read [upgrade notes](UPGRADE_NOTES.md#v1---v2)
21
+ - Added better pagination methods for GroupList & FileList
22
+ - Improved documentation and install instructions
23
+ - Added CI
21
24
 
22
- ### Added
23
- - Support for `store` flag in [Upload API](https://uploadcare.com/documentation/upload/) methods
24
- - Methods to store/delete multiple files at once: `Uploadcare::Api#store_files` & `Uploadcare::Api#delete_files`
25
+ ## 3.0.3-dev 2020-03-13
25
26
 
26
- ### Changed
27
- - Upgraded to REST API v0.5
28
- - All POST/PUT/DELETE params are now being sent as JSON instead of being form-encoded
29
- - Pagination implementation for files and groups
27
+ - Added better pagination and iterators for GroupList & FileList
30
28
 
31
- ## 1.1.0 - 2017-03-21
29
+ ## 3.0.2-dev 2020-03-11
32
30
 
33
- ### Added
34
- - Added to new methods to `Uploadcare::Api::File`, `#internal_copy` and `#external_copy`.
35
- - Added support of [secure authorization](https://uploadcare.com/documentation/rest/#request) for REST API. It is now used by default (can be overriden in config)
31
+ - Expanded File and Group entities
32
+ - Changed user agent syntax
36
33
 
37
- ### Fixed
38
- - Fixed middleware names that could break other gems ([#13](https://github.com/uploadcare/uploadcare-ruby/issues/13)).
34
+ ## 3.0.1-dev 2020-03-11
39
35
 
40
- ### Deprecated
41
- - `Uploadcare::Api::File#copy` in favor of `#internal_copy` and `#external_copy`.
36
+ - Added Upload/group functionality
37
+ - Added user API
38
+ - Added user agent
39
+ - Isolated clients, entities and concerns
40
+ - Expanded documentation
42
41
 
42
+ ## 3.0.0-dev 2020-02-18
43
43
 
44
- ## 1.0.6, 2017-01-30
44
+ ### Changed
45
+ - Rewrote gem from scratch
45
46
 
46
47
  ### Added
47
- - Ruby version and public API key sent via User-Agent header (can be overriden in config)
48
-
49
- ### Fixed
50
- - Incorrect dependencies
51
-
52
48
 
53
- [Unreleased]: https://github.com/uploadcare/uploadcare-ruby/compare/v2.1.1...HEAD
54
- [2.1.1]: https://github.com/uploadcare/uploadcare-ruby/compare/v2.0.0...v2.1.1
49
+ - Client wrappers for REST API
50
+ - Serializers for REST API
51
+ - Client wrappers for Upload API
52
+ - Serializers for Upload API
53
+ - rdoc documentation
data/DEVELOPMENT.md ADDED
@@ -0,0 +1,18 @@
1
+ ## How to contribute
2
+
3
+ https://github.com/uploadcare/.github/blob/master/CONTRIBUTING.md
4
+
5
+ ## Useful docs
6
+
7
+ ### Uploadcare:
8
+
9
+ * https://uploadcare.com/docs/api_reference/
10
+ * https://uploadcare.com/api-refs/rest-api/
11
+
12
+ ### ApiStruct:
13
+
14
+ * https://github.com/rubygarage/api_struct/
15
+
16
+ ## Uploadcare-ruby gem architecture
17
+
18
+ ![http://www.plantuml.com/plantuml/uml/bPHDRzj838Rl-XM4zn1WiHRsOoyR88iuXOFcKWHDqcimaLxBquvcL9AowtxyzqepqYGrYY050cH69X-IByav5pMiVUkAed96X5QTfIy54T7jrWgDVrx16rE1De6fGKkzW2NQB9VB-7_zoRIT0zLmQ8oYfXQw3RMS9ZFgEnTCFLqsrk7UMT7YsnnsxTNguIZoNNIg38DMrrU4P2DWQvpz32wZzPtqnha3MStXXH9rIe8qq2jduPMSEO3_Y7x6rzJ0WwD3fjOK7jwZKg4DXvOOqWKlIB6klAZn5JBPS3v7UOQJ83j9-RnAASsNQHNlPsTdFv3iKJu9yJjT1gPBwp0ZHGCZdMDqHPP-LkPH-YGIjSQR1aACZpr4HnMFElApudwryMyXeUSAzDl5nSMGn0XIUB71HqLJrosacAj_4vHwGKtMqp_bd-LVongxH-0DU6ShJFMyCsn3BxI5wy1JQnDudS77LMJTfdfNjUaKFDnrb4Uc23KgMsDWXprfI7lICPHEKj4d4PBqe0SpfXmyTHnsjivZTZBDQlca8S5NO2zJ2Mlcm5GPhRPWYMEB-6ax71tusG8MY-Xu7praiI0sLY13dpceEYHuDBQRk6KCxTbBdc7QMzrI5MhGlt__bx4f-BqcZlNDm5Rp0K9cAZbcgcmH9uTxJrR9DCRw56-_XSSEF7vke4SvFSfnRTYqUJmXo5qqd5VDFhZfVKeRFIH4kwdthszlhwaRAL6gED2MCVJay8A1pfDyOnjlj6VCCGBBcEMgiuFFr__dD-mqx_VJ1sZ-DTPKf4joc_RlzBdNosC_sHLvOSe9ESFAUVIBYLWcwOeyJ-NCE8Ul-zPz1m00](http://www.plantuml.com/plantuml/svg/bPHDRzj838Rl-XM4zn1WiHRsOoyR88iuXOFcKWHDqcimaLxBquvcL9AowtxyzqepqYGrYY050cH69X-IByav5pMiVUkAed96X5QTfIy54T7jrWgDVrx16rE1De6fGKkzW2NQB9VB-7_zoRIT0zLmQ8oYfXQw3RMS9ZFgEnTCFLqsrk7UMT7YsnnsxTNguIZoNNIg38DMrrU4P2DWQvpz32wZzPtqnha3MStXXH9rIe8qq2jduPMSEO3_Y7x6rzJ0WwD3fjOK7jwZKg4DXvOOqWKlIB6klAZn5JBPS3v7UOQJ83j9-RnAASsNQHNlPsTdFv3iKJu9yJjT1gPBwp0ZHGCZdMDqHPP-LkPH-YGIjSQR1aACZpr4HnMFElApudwryMyXeUSAzDl5nSMGn0XIUB71HqLJrosacAj_4vHwGKtMqp_bd-LVongxH-0DU6ShJFMyCsn3BxI5wy1JQnDudS77LMJTfdfNjUaKFDnrb4Uc23KgMsDWXprfI7lICPHEKj4d4PBqe0SpfXmyTHnsjivZTZBDQlca8S5NO2zJ2Mlcm5GPhRPWYMEB-6ax71tusG8MY-Xu7praiI0sLY13dpceEYHuDBQRk6KCxTbBdc7QMzrI5MhGlt__bx4f-BqcZlNDm5Rp0K9cAZbcgcmH9uTxJrR9DCRw56-_XSSEF7vke4SvFSfnRTYqUJmXo5qqd5VDFhZfVKeRFIH4kwdthszlhwaRAL6gED2MCVJay8A1pfDyOnjlj6VCCGBBcEMgiuFFr__dD-mqx_VJ1sZ-DTPKf4joc_RlzBdNosC_sHLvOSe9ESFAUVIBYLWcwOeyJ-NCE8Ul-zPz1m00)
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in uploadcare-ruby.gemspec
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2018 Uploadcare, LLC
3
+ Copyright (c) 2021 Uploadcare Inc.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,117 +1,92 @@
1
- [![Build Status][travis-img]][travis]
2
- [![Coverage Status][coverals-img]][coverals]
1
+ # Ruby integration for Uploadcare
2
+
3
+ ![license](https://img.shields.io/badge/license-MIT-brightgreen.svg)
4
+ [![Build Status][actions-img]][actions-badge]
3
5
  [![Uploadcare stack on StackShare][stack-img]][stack]
6
+ <!--[![Coverage Status][coverals-img]][coverals]-->
4
7
 
5
- [travis-img]: https://secure.travis-ci.org/uploadcare/uploadcare-ruby.png?branch=master
6
- [travis]: http://travis-ci.org/uploadcare/uploadcare-ruby
7
- [coverals-img]: https://coveralls.io/repos/github/uploadcare/uploadcare-ruby/badge.svg?branch=master
8
- [coverals]: https://coveralls.io/github/uploadcare/uploadcare-ruby?branch=master
8
+ [actions-badge]: https://github.com/uploadcare/uploadcare-ruby/actions/workflows/ruby.yml
9
+ [actions-img]: https://github.com/uploadcare/uploadcare-ruby/actions/workflows/ruby.yml/badge.svg
10
+ [coverals-img]: https://coveralls.io/repos/github/uploadcare/uploadcare-ruby/badge.svg?branch=main
11
+ [coverals]: https://coveralls.io/github/uploadcare/uploadcare-ruby?branch=main
9
12
  [stack-img]: https://img.shields.io/badge/tech-stack-0690fa.svg?style=flat
10
13
  [stack]: https://stackshare.io/uploadcare/stacks/
11
14
 
12
- A [Ruby](https://www.ruby-lang.org/en/) wrapper for [Uploadcare](https://uploadcare.com).
15
+ Uploadcare Ruby integration handles uploads and further operations with files by
16
+ wrapping Upload and REST APIs.
17
+
18
+ * [Installation](#installation)
19
+ * [Usage](#usage)
20
+ * [Uploading files](#uploading-files)
21
+ * [Uploading and storing a single file](#uploading-and-storing-a-single-file)
22
+ * [Multiple ways to upload files](#multiple-ways-to-upload-files)
23
+ * [Uploading options](#uploading-options)
24
+ * [File management](#file-management)
25
+ * [File](#file)
26
+ * [FileList](#filelist)
27
+ * [Pagination](#pagination)
28
+ * [Group](#group)
29
+ * [GroupList](#grouplist)
30
+ * [Webhook](#webhook)
31
+ * [Project](#project)
32
+ * [Conversion](#conversion)
33
+ * [Useful links](#useful-links)
34
+
35
+ ## Requirements
36
+ * ruby 2.4+
37
+
38
+ ## Compatibility
39
+
40
+ Note that `uploadcare-ruby` **3.x** is not backward compatible with
41
+ **[2.x](https://github.com/uploadcare/uploadcare-ruby/tree/v2.x)**.
13
42
 
14
43
  ## Installation
15
44
 
16
- Installing `uploadcare-ruby` is quite simple and takes a couple of steps.
17
- First of, add the following line to your app's Gemfile:
45
+ Add this line to your application's Gemfile:
18
46
 
19
47
  ```ruby
20
48
  gem 'uploadcare-ruby'
21
49
  ```
22
50
 
23
- Once you've added the line, execute this:
51
+ And then execute:
24
52
 
25
- ```shell
26
- $ bundle install
27
- ```
53
+ $ bundle
28
54
 
29
- Or that (for manual install):
55
+ If already not, create your project in [Uploadcare dashboard](https://uploadcare.com/dashboard/?utm_source=github&utm_medium=referral&utm_campaign=uploadcare-ruby) and copy
56
+ its API keys from there.
30
57
 
31
- ```shell
32
- $ gem install uploadcare-ruby
58
+ Set your Uploadcare keys in config file or through environment variables:
59
+ ```bash
60
+ export UPLOADCARE_PUBLIC_KEY=demopublickey
61
+ export UPLOADCARE_SECRET_KEY=demoprivatekey
33
62
  ```
34
63
 
35
- ## Initialization
36
-
37
- Init is simply done through creating an API object.
64
+ Or configure your app yourself if you are using different way of storing keys.
65
+ Gem configuration is available in `Uploadcare.configuration`. Full list of
66
+ settings can be seen in [`lib/uploadcare.rb`](lib/uploadcare.rb)
38
67
 
39
68
  ```ruby
40
- require 'uploadcare'
41
-
42
- @api = Uploadcare::Api.new # default settings are used
43
-
44
- @api = Uploadcare::Api.new(settings) # using user-defined settings
69
+ # your_config_initializer_file.rb
70
+ Uploadcare.config.public_key = 'demopublickey'
71
+ Uploadcare.config.secret_key = 'demoprivatekey'
45
72
  ```
46
73
 
47
- Here's how the default settings look like:
48
-
49
- ``` ruby
50
- {
51
- public_key: 'demopublickey', # you need to override this
52
- private_key: 'demoprivatekey', # you need to override this
53
- upload_url_base: 'https://upload.uploadcare.com',
54
- api_url_base: 'https://api.uploadcare.com',
55
- static_url_base: 'https://ucarecdn.com',
56
- api_version: '0.5',
57
- cache_files: true,
58
- autostore: :auto,
59
- auth_scheme: :secure
60
- }
61
- ```
62
-
63
- You're free to use both `demopublickey` and `demoprivatekey`
64
- for initial testing purposes. We wipe out files loaded to our
65
- demo account periodically. For a better experience,
66
- consider creating an Uploadcare account. Check out
67
- [this](http://kb.uploadcare.com/article/234-uc-project-and-account)
68
- article to get up an running in minutes.
69
-
70
- Please note, in order to use [Upload API](https://uploadcare.com/documentation/upload/)
71
- you will only need the public key alone. However, using
72
- [REST API](https://uploadcare.com/documentation/rest/) requires you to
73
- use both public and private keys for authentication.
74
- While “private key” is a common way to name a key from an
75
- authentication key pair, the actual thing for our `auth-param` is `secret_key`.
76
-
77
- `:autostore` option allows you to set the default storage
78
- behaviour upon uploads. For more info see [`store` flag][uploads from url] for
79
- uploads via URL and [`UPLOADCARE_STORE` flag][in-body file uploads] for file uploads
80
-
81
- [in-body file uploads]: https://uploadcare.com/documentation/upload/#upload-body
82
- [uploads from url]: https://uploadcare.com/documentation/upload/#from-url
83
-
84
74
  ## Usage
85
75
 
86
- This section contains practical usage examples. Please note,
87
- everything that follows gets way more clear once you've looked
88
- through our docs [intro](https://uploadcare.com/documentation/).
76
+ This section contains practical usage examples. Please note, everything that
77
+ follows gets way more clear once you've looked through our
78
+ [docs](https://uploadcare.com/docs/?utm_source=github&utm_medium=referral&utm_campaign=uploadcare-ruby).
89
79
 
90
- ### Basic usage: uploading a single file, manipulations
80
+ ### Uploading files
81
+ #### Uploading and storing a single file
91
82
 
92
83
  Using Uploadcare is simple, and here are the basics of handling files.
93
84
 
94
- First of, create the API object:
95
-
96
- ```ruby
97
- @api = Uploadcare::Api.new(CONFIG)
98
-
99
- ```
100
-
101
- And yeah, now you can upload a file:
102
-
103
85
  ```ruby
104
86
  @file_to_upload = File.open("your-file.png")
105
87
 
106
- @uc_file = @api.upload(@file_to_upload)
107
- # => #<Uploadcare::Api::File ...
108
- ```
109
-
110
- Then, let's check out UUID and URL of the
111
- file you've just uploaded:
88
+ @uc_file = Uploadcare::Uploader.upload(@file_to_upload)
112
89
 
113
- ```ruby
114
- # file uuid (you'd probably want to store those somewhere)
115
90
  @uc_file.uuid
116
91
  # => "dc99200d-9bd6-4b43-bfa9-aa7bfaefca40"
117
92
 
@@ -120,10 +95,9 @@ file you've just uploaded:
120
95
  # => "https://ucarecdn.com/dc99200d-9bd6-4b43-bfa9-aa7bfaefca40/"
121
96
  ```
122
97
 
123
- Your might then want to store or delete the uploaded file.
124
- Storing files could be crucial if you aren't using the
125
- “Automatic file storing” option for your Uploadcare project.
126
- If not stored manually or automatically, files get deleted
98
+ Your might then want to store or delete the uploaded file. Storing files could
99
+ be crucial if you aren't using the “Automatic file storing” option for your
100
+ Uploadcare project. If not stored manually or automatically, files get deleted
127
101
  within a 24-hour period.
128
102
 
129
103
  ```ruby
@@ -136,51 +110,28 @@ within a 24-hour period.
136
110
  # => #<Uploadcare::Api::File ...
137
111
  ```
138
112
 
139
- ### Uploading a file from URL
113
+ #### Multiple ways to upload files
140
114
 
141
- Now, this one is also quick. Just pass your URL into our API
142
- and you're good to go.
115
+ Uploadcare supports multiple ways to upload files:
143
116
 
144
117
  ```ruby
145
- # the smart upload
146
- @file = @api.upload "http://your.awesome/avatar.jpg"
147
- # => #<Uploadcare::Api::File ...
148
-
149
- # use this one if you want to explicitly upload from URL
150
- @file = @api.upload_from_url "http://your.awesome/avatar.jpg"
151
- # => #<Uploadcare::Api::File ...
118
+ # Smart upload - detects type of passed object and picks appropriate upload method
119
+ Uploadcare::Uploader.upload('https://placekitten.com/96/139')
152
120
  ```
153
- Keep in mind that providing invalid URL
154
- will raise `ArgumentError`.
155
-
156
- ### Uploading multiple files
157
121
 
158
- Uploading multiple files is as simple as passing an array
159
- of `File` instances into our API.
122
+ There are explicit ways to select upload type:
160
123
 
161
124
  ```ruby
162
- file1 = File.open("path/to/your/file.png")
163
- file2 = File.open("path/to/your/another-file.png")
164
- files = [file1, file2]
125
+ files = [File.open('1.jpg'), File.open('1.jpg']
126
+ Uploadcare::Uploader.upload_files(files)
165
127
 
166
- @uc_files = @api.upload files
167
- # => [#<Uploadcare::Api::File uuid="dc99200d-9bd6-4b43-bfa9-aa7bfaefca40">,
168
- # #<Uploadcare::Api::File uuid="96cdc400-adc3-435b-9c94-04cd87633fbb">]
169
- ```
170
-
171
- In case of multiple input, the respective output would also be an array.
172
- You can iterate through the array to address to single files.
173
- You might also want to request more info about a file using `load_data`.
128
+ Uploadcare::Uploader.upload_from_url('https://placekitten.com/96/139')
174
129
 
175
- ```ruby
176
- @uc_files[0]
177
- # => #<Uploadcare::Api::File uuid="dc99200d-9bd6-4b43-bfa9-aa7bfaefca40">
178
-
179
- @uc_files[1].load_data
180
- # => #<Uploadcare::Api::File uuid="96cdc400-adc3-435b-9c94-04cd87633fbb", original_file_url="https://ucarecdn.com/96cdc400-adc3-435b-9c94-04cd87633fbb/samuelzeller118195.jpg", image_info={"width"=>4896, "geo_location"=>nil, "datetime_original"=>nil, "height"=>3264}, ....>
130
+ # multipart upload - can be useful for files bigger than 10 mb
131
+ Uploadcare::Uploader.multipart_upload(File.open('big_file.bin'))
181
132
  ```
182
133
 
183
- ### Upload options
134
+ #### Uploading options
184
135
 
185
136
  You can override global [`:autostore`](#initialization) option for each upload request:
186
137
 
@@ -189,246 +140,89 @@ You can override global [`:autostore`](#initialization) option for each upload r
189
140
  @api.upload_from_url(url, store: :auto)
190
141
  ```
191
142
 
192
- ### `File` object
193
-
194
- Now that we've already outlined using arrays of `File` instances
195
- to upload multiple files, let's fix on the `File` itself.
196
- It's the the primary object for Uploadcare API.
197
- Basically, it's an avatar for a file you uploaded.
198
- And all the further operations are performed using this avatar,
199
- the `File` object.
200
-
143
+ ### File management
144
+ Most methods are also available through `Uploadcare::Api` object:
201
145
  ```ruby
202
- @file_to_upload = File.open("your-file.png")
203
-
204
- @uc_file = @api.upload(@file_to_upload)
205
- # => #<Uploadcare::Api::File ...
206
-
207
- @uc_file.uuid
208
- # => "dc99200d-9bd6-4b43-bfa9-aa7bfaefca40"
209
-
210
- @uc_file.cdn_url
211
- # => "https://ucarecdn.com/dc99200d-9bd6-4b43-bfa9-aa7bfaefca40/"
146
+ # Same as Uploadcare::Uploader.upload
147
+ Uploadcare::Api.upload('https://placekitten.com/96/139')
212
148
  ```
213
149
 
214
- Please note, all the data associated with files is only accessible
215
- through separate HTTP requests only. So if you don't specifically
216
- need file data (filenames, image dimensions, etc.), you'll be just
217
- fine with using `:uuid` and `:cdn_url` methods for file output:
150
+ Entities are representations of objects in Uploadcare cloud.
218
151
 
219
- ```erb
220
- <img src="#{@file.cdn_url}"/>
221
- ```
222
-
223
- Great, we've just lowered a precious loading time.
224
- However, if you do need the data, you can always request
225
- it manually:
226
-
227
- ```ruby
228
- @uc_file.load_data
229
- ```
230
-
231
- That way your file object will respond to any method described
232
- in [API docs](https://uploadcare.com/documentation/rest/#file).
233
- Basically, that's an an OpenStruct, so you know what to do:
234
-
235
- ```ruby
236
- @uc_file.original_filename
237
- # => "logo.png"
238
-
239
- @uc_file.image_info
240
- # => {"width"=>397, "geo_location"=>nil, "datetime_original"=>nil, "height"=>81}
241
- ```
152
+ #### File
242
153
 
243
- ### `File` object from UUID or CDN URL
244
-
245
- `File` objects are needed to manipulate files on our CDN.
246
- The usual case would be you as a client storing file UUIDs
247
- or CDN URLs somewhere on your side, e.g. in a database.
248
- This is how you can use those to create `File` objects:
249
-
250
- ```ruby
251
- # file object from UUID
252
- @file = @api.file "dc99200d-9bd6-4b43-bfa9-aa7bfaefca40"
253
- # => #<Uploadcare::Api::File uuid="dc99200d-9bd6-4b43-bfa9-aa7bfaefca40"
254
-
255
- # file object from CDN URL
256
- @file = @api.file "https://ucarecdn.com/dc99200d-9bd6-4b43-bfa9-aa7bfaefca40/"
257
- # => #<Uploadcare::Api::File uuid="dc99200d-9bd6-4b43-bfa9-aa7bfaefca40"
258
-
259
- # note, files you generate won't be loaded on init,
260
- # you'll need to load those manually
261
- @file.is_loaded?
262
- # => false
263
- ```
264
-
265
- ### Operations
266
-
267
- Another way to manipulate files on CDN is through operations.
268
- This is particularly useful for images.
269
- We've got on-the-fly crop, resize, rotation, format conversions, and
270
- [more](https://uploadcare.com/documentation/cdn/).
271
- Image operations are there to help you build responsive designs,
272
- generate thumbnails and galleries, change formats, etc.
273
- Currently, this gem has no specific methods for image operations,
274
- we're planning to implement those in further versions.
275
- However, we do support applying image operations through
276
- adding them to CDN URLs. That's an Uploadcare CDN-native
277
- way described in our [docs](https://uploadcare.com/documentation/cdn/).
154
+ File entity contains its metadata.
278
155
 
279
156
  ```ruby
280
- @file = @api.file "https://ucarecdn.com/dc99200d-9bd6-4b43-bfa9-aa7bfaefca40/-/crop/150x150/center/-/format/png/"
281
- # => #<Uploadcare::Api::File uuid="dc99200d-9bd6-4b43-bfa9-aa7bfaefca40"
282
-
283
- @file.operations
284
- # => ["crop/150x150/center", "format/png"]
285
-
286
- # note that by default :cdn_url method returns URLs with no operations:
287
- @file.cdn_url
288
- # => "https://ucarecdn.com/dc99200d-9bd6-4b43-bfa9-aa7bfaefca40/""
289
-
290
- # you can pass "true" into the :cdn_url method to get URL including operations:
291
- @file.cdn_url(true)
292
- # => "https://ucarecdn.com/a8775cf7-0c2c-44fa-b071-4dd48637ecac/-/crop/150x150/center/-/format/png/"
293
-
294
- # there also are specific methods to either dump or include image operations
295
- # in the output URL:
296
- @file.cdn_url_with_operations
297
- @file.cdn_url_without_operations
298
- ```
299
-
300
- While there's no operation wrapper, the best way of handling operations
301
- is through adding them to URLs as strings:
302
-
303
- ```ruby
304
- <img src="#{file.cdn_url}-/crop/#{width}x#{height}/center/"/>
305
- # or something like that
306
- ```
307
-
308
- ### Copying files
309
-
310
- You can also create file copies using our API.
311
- There are multiple ways of creating those.
312
- Also, copying is important for image files because
313
- it allows you to “apply” all the CDN operations
314
- specified in the source URL to a separate static image.
315
-
316
- First of all, a copy of your file can be put in the Uploadcare storage.
317
- This is called “internal copy”, and here's how it works:
318
-
319
- ```ruby
320
- @uc_file.internal_copy
321
-
322
- # =>
323
- {
324
- "type"=>"file",
325
- "result"=> {
326
- "uuid"=>"a191a3df-2c43-4939-9590-784aa371ad6d",
327
- "original_file_url"=>"https://ucarecdn.com/a191a3df-2c43-4939-9590-784aa371ad6d/19xldj.jpg",
328
- "image_info"=>nil,
329
- "datetime_stored"=>nil,
330
- "mime_type"=>"application/octet-stream",
331
- "is_ready"=>true,
332
- "url"=>"https://api.uploadcare.com/files/a191a3df-2c43-4939-9590-784aa371ad6d/",
333
- "original_filename"=>"19xldj.jpg",
334
- "datetime_uploaded"=>"2017-02-10T14:14:18.690581Z",
335
- "size"=>0,
336
- "is_image"=>nil,
337
- "datetime_removed"=>nil,
338
- "source"=>"/4ea293d5-153f-422f-a24e-350237109606/"
339
- }
340
- }
341
- ```
342
-
343
- Once the procedure is complete, a copy would be a separate file
344
- with its own UUID and attributes.
345
-
346
- `#internal_copy` can optionally be used with the options hash argument.
347
- The available options are:
348
-
349
- - *store*
350
-
351
- By default a copy is created without “storing”.
352
- Which means it will be deleted within a 24-hour period.
353
- You can make your output copy permanent by passing the
354
- `store: true` option to the `#internal_copy` method.
355
-
356
- Example:
357
-
358
- ```ruby
359
- @uc_file.internal_copy(store: true)
360
- ```
361
-
362
- - *strip_operations*
157
+ @file = Uploadcare::File.file('FILE_ID_IN_YOUR_PROJECT')
158
+ {"datetime_removed"=>nil,
159
+ "datetime_stored"=>"2020-01-16T15:03:15.315064Z",
160
+ "datetime_uploaded"=>"2020-01-16T15:03:14.676902Z",
161
+ "image_info"=>
162
+ {"color_mode"=>"RGB",
163
+ "orientation"=>nil,
164
+ "format"=>"JPEG",
165
+ "sequence"=>false,
166
+ "height"=>183,
167
+ "width"=>190,
168
+ "geo_location"=>nil,
169
+ "datetime_original"=>nil,
170
+ "dpi"=>nil},
171
+ "is_image"=>true,
172
+ "is_ready"=>true,
173
+ "mime_type"=>"image/jpeg",
174
+ "original_file_url"=>
175
+ "https://ucarecdn.com/FILE_ID_IN_YOUR_PROJECT/imagepng.jpeg",
176
+ "original_filename"=>"image.png.jpeg",
177
+ "size"=>5345,
178
+ "url"=>
179
+ "https://api.uploadcare.com/files/FILE_ID_IN_YOUR_PROJECT/",
180
+ "uuid"=>"8f64f313-e6b1-4731-96c0-6751f1e7a50a"}
363
181
 
364
- If your file is an image and you applied some operations to it,
365
- then by default the same set of operations is also applied to a copy.
366
- You can override this by passing `strip_operations: true` to the
367
- `#internal_copy` method.
182
+ @file.store # copies file, returns a new (copied) file metadata
368
183
 
369
- Example:
184
+ @file.store # stores file, returns updated metadata
370
185
 
371
- ```ruby
372
- file = @api.file "https://ucarecdn.com/24626d2f-3f23-4464-b190-37115ce7742a/-/resize/50x50/"
373
- file.internal_copy
374
- # => This will trigger POST /files/ with {"source": "https://ucarecdn.com/24626d2f-3f23-4464-b190-37115ce7742a/-/resize/50x50/"} in the body
375
- file.internal_copy(strip_operations: true)
376
- # => This will trigger POST /files/ with {"source": "https://ucarecdn.com/24626d2f-3f23-4464-b190-37115ce7742a/"} in the body
377
- ```
378
-
379
- Another option is copying your file to a custom storage.
380
- We call it “external copy” and here's the usage example:
381
-
382
- ```ruby
383
- @uc_file.external_copy('my_custom_storage_name')
384
-
385
- # =>
386
- {
387
- "type"=>"url",
388
- "result"=>"s3://my_bucket_name/c969be02-9925-4a7e-aa6d-b0730368791c/view.png"
389
- }
186
+ @file.delete #deletes file. Returns updated metadata
390
187
  ```
391
188
 
392
- First argument of the `#external_copy` method is a name of
393
- a custom destination storage for your file.
394
-
395
- There's also an optional second argument — options hash. The available options are:
396
-
397
- - *make_public*
398
-
399
- Make a copy available via public links. Can be either `true` or `false`.
400
-
401
- - *pattern*
189
+ Metadata of deleted files is stored permanently.
402
190
 
403
- Name pattern for a copy. If the parameter is omitted, custom storage pattern is used.
191
+ #### FileList
404
192
 
405
- - *strip_operations*
406
-
407
- Same as for `#internal_copy`
408
-
409
- You might want to learn more about
410
- [storage options](https://uploadcare.com/documentation/storages/) or
411
- [copying files](https://uploadcare.com/documentation/rest/#files-post)
412
- with Uploadcare.
413
-
414
-
415
- ### File lists
416
-
417
- `Uploadcare::Api::FileList` represents the whole collection of files (or it's subset) and privides a way to iterate through it, making pagination transparent. FileList objects can be created using `Uploadcare::Api#file_list` method.
193
+ `Uploadcare::Entity::FileList` represents the whole collection of files (or it's
194
+ subset) and provides a way to iterate through it, making pagination transparent.
195
+ FileList objects can be created using `Uploadcare::Entity.file_list` method.
418
196
 
419
197
  ```ruby
420
- @list = @api.file_list # => instance of Uploadcare::Api::FileList
198
+ @list = Uploadcare::Entity.file_list
199
+ # Returns instance of Uploadcare::Api::FileList
200
+ <Hashie::Mash
201
+ next=nil
202
+ per_page=100
203
+ previous=nil
204
+ results=[
205
+ # Array of Entity::File
206
+ ]
207
+ total=8>
208
+ # load last page of files
209
+ @files = @list.files
210
+ # load all files
211
+ @all_files = @list.load
421
212
  ```
422
213
 
423
- This method accepts some options to controll which files should be fetched and how they should be fetched:
214
+ This method accepts some options to controll which files should be fetched and
215
+ how they should be fetched:
424
216
 
425
- - **:limit** - Controls page size. Accepts values from 1 to 1000, defaults to 100.
426
- - **:stored** - Can be either `true` or `false`. When true, file list will contain only stored files. When false - only not stored.
427
- - **:removed** - Can be either `true` or `false`. When true, file list will contain only removed files. When false - all except removed. Defaults to false.
428
- - **:ordering** - Controls the order of returned files. Available values: `datetime_updated`, `-datetime_updated`, `size`, `-size`. Defaults to `datetime_uploaded`. More info can be found [here](https://uploadcare.com/documentation/rest/#file-files)
429
- - **:from** - Specifies the starting point for a collection. Resulting collection will contain files from the given value and to the end in a direction set by an **ordering** option. When files are ordered by datetime_updated in any direction, accepts either a `DateTime` object or an ISO 8601 string. When files are ordered by size, acepts non-negative integers (size in bytes). More info can be found [here](https://uploadcare.com/documentation/rest/#file-files)
217
+ - **:limit** Controls page size. Accepts values from 1 to 1000, defaults to 100.
218
+ - **:stored** Can be either `true` or `false`. When true, file list will contain only stored files. When false only not stored.
219
+ - **:removed** Can be either `true` or `false`. When true, file list will contain only removed files. When false all except removed. Defaults to false.
220
+ - **:ordering** Controls the order of returned files. Available values: `datetime_updated`, `-datetime_updated`, `size`, `-size`. Defaults to `datetime_uploaded`. More info can be found [here](https://uploadcare.com/documentation/rest/#file-files/?utm_source=github&utm_medium=referral&utm_campaign=uploadcare-ruby).
221
+ - **:from** Specifies the starting point for a collection. Resulting collection will contain files from the given value and to the end in a direction set by an **ordering** option. When files are ordered by `datetime_updated` in any direction, accepts either a `DateTime` object or an ISO 8601 string. When files are ordered by size, accepts non-negative integers (size in bytes). More info can be found [here](https://uploadcare.com/documentation/rest/#file-files/?utm_source=github&utm_medium=referral&utm_campaign=uploadcare-ruby).
430
222
 
431
- Options used to create a file list can be accessed through `#options` method. Note that, once set, they don't affect file fetching process anymore and are stored just for your convenience. That is why they are frozen.
223
+ Options used to create a file list can be accessed through `#options` method.
224
+ Note that, once set, they don't affect file fetching process anymore and are
225
+ stored just for your convenience. That is why they are frozen.
432
226
 
433
227
  ```ruby
434
228
  options = {
@@ -438,286 +232,315 @@ options = {
438
232
  from: "2017-01-01T00:00:00",
439
233
  }
440
234
  @list = @api.file_list(options)
441
- @list.options # => same as options hash above, but frozen
442
- ```
443
-
444
- `Uploadcare::Api::FileList` implements Enumerable interface and holds a collection of `Uploadcare::Api::File` objects, as well as some meta information.
445
-
446
- ```ruby
447
- @list = @api.file_list
448
- @list.total # => 1977
449
- @list.meta # => {
450
- # "next"=> "https://api.uploadcare.com/files/?from=2017-03-09T10%3A30%3A01.877590%2B00%3A00&offset=0",
451
- # "previous"=>nil,
452
- # "total"=>1977,
453
- # "per_page"=>100
454
- # }
455
-
456
- # Enumerable interface
457
- @list.first(5) # => array of 5 x Uploadcare::Api::File
458
- @list.each{|file| puts file.original_filename}
459
- @list.map{|file| file.uuid}
460
- @list.reduce(0){|overall_size, file| overall_size += file.size}
461
- # ...
462
235
  ```
463
236
 
464
- On the inside, `FileList` loada files page by page. First page is loaded when you call `Uploadcare::Api#file_list` and subsequent pages are being loaded when needed. The size of pages is controlled by a `:limit` option.
465
-
466
- Currently loaded files are available through `FileList#objects`. `FileList#loaded` method returns the number of currently loaded files.
467
-
237
+ To simply get all associated objects:
468
238
  ```ruby
469
- @list = @api.file_list(limit: 5) # will load first 5 files
470
- @list.loaded # => 5
471
- @list.fully_loaded? # => false
472
-
473
- @list.objects # => array of 5 x Uploadcare::Api::File
474
- @list.objects[4] # => #<Uploadcare::Api::File ...>
475
- @list.objects[5] # => nil (since 6th file is not yet loaded)
476
-
477
- @list[4] # won't load anything, because 5 files are already loaded
478
- @list[5] # will load the next page
479
- @list.loaded # => 10
480
-
481
- # Note that the example below will load all the files left, page by page,
482
- # and return the count only when they all will be loaded
483
- @list.count # => 132
484
- @list.fully_loaded? # => true
239
+ @list.all # => returns Array of Files
485
240
  ```
486
241
 
487
- Loaded files are preserved when `break` statement or an exception occures inside a block provided to #each, #map, etc.
242
+ #### Pagination
488
243
 
244
+ Initially, `FileList` is a paginated collection. It can be navigated using following methods:
489
245
  ```ruby
490
- @list = @api.file_list(limit: 10)
491
- @list.loaded # => 10
492
-
493
- i = 0
494
- @list.map do |file|
495
- raise if i >= 19
496
- i += 1
497
- file.uuid
498
- end # => RuntimeError
499
-
500
- @list.loaded # => 20
246
+ @file_list = Uploadcare::Entity::FileList.file_list
247
+ # Let's assume there are 250 files in cloud. By default, UC loads 100 files. To get next 100 files, do:
248
+ @next_page = @file_list.next_page
249
+ # To get previous page:
250
+ @previous_page = @next_page.previous_page
501
251
  ```
502
252
 
503
-
504
- ### Store / delete multiple files at once
505
-
506
- There are two methods to do so: `Uploadcare::Api#store_files` and
507
- `Uploadcare::Api#delete_files`. Both of them accept a list of either
508
- UUIDs or `Uploadcare::Api::File`s:
509
-
253
+ Alternatively, it's possible to iterate through full list of groups or files with `each`:
510
254
  ```ruby
511
- uuids_to_store = ['f5c477e0-22af-469d-859a-712e14e14361', 'ec72c6eb-5ea8-4057-a009-52ffffb27c94']
512
- @api.store_files(uuids_to_store)
513
- # => {'status' => 'ok', 'problems' => {}, 'result' => [{...}, {...}]}
514
-
515
- old_files = @api.file_list(stored: true, ordering: '-datetime_uploaded', from: "2015-01-01T00:00:00")
516
- old_files.each_slice(100) do |batch|
517
- response = @api.delete_files(batch)
518
- # Do something with response if you need to
255
+ @list.each do |file|
256
+ p file.url
519
257
  end
520
258
  ```
521
259
 
522
- Our API supports up to 100 files per request. Calling `#store_files` or
523
- `#delete_files` with more than 100 files at once will cause an ArgumentError.
260
+ #### Group
524
261
 
525
- For more details see our [documentation on batch file storage/deletion](https://uploadcare.com/documentation/rest/#files-storage)
526
-
527
- ### `Group` object
528
-
529
- Groups are structures intended to organize sets of separate files.
530
- Each group is assigned UUID.
531
- Note, group UUIDs include a `~#{files_count}` part at the end.
262
+ Groups are structures intended to organize sets of separate files. Each group is
263
+ assigned UUID. Note, group UUIDs include a `~#{files_count}` part at the end.
532
264
  That's a requirement of our API.
533
265
 
534
266
  ```ruby
535
- # group can be created from an array of Uploadcare files
267
+ # group can be created from an array of Uploadcare files (UUIDs)
268
+ @file = '134dc30c-093e-4f48-a5b9-966fe9cb1d01'
269
+ @file2 = '134dc30c-093e-4f48-a5b9-966fe9cb1d02'
536
270
  @files_ary = [@file, @file2]
537
- @files = @api.upload @files_ary
538
- @group = @api.create_group @files
539
- # => #<Uploadcare::Api::Group uuid="0d192d66-c7a6-4465-b2cd-46716c5e3df3~2", files_count=2 ...
540
-
541
- # another way to from a group is via an array of strings holding UUIDs
542
- @uuids_ary = ["c969be02-9925-4a7e-aa6d-b0730368791c", "c969be02-9925-4a7e-aa6d-b0730368791c"]
543
- @group = @api.create_group @uuids_ary
544
- # => #<Uploadcare::Api::Group uuid="0d192d66-c7a6-4465-b2cd-46716c5e3df3~2", files_count=2 ...
271
+ @files = Uploadcare::Uploader.upload @files_ary
272
+ @group = Uploadcare::Group.create @files
545
273
 
546
- # also, you can create a group object via group UUID
547
- @group_uloaded = @api.group "#{uuid}"
274
+ # group can be stored by group ID. It means that all files of a group will be stored on Uploadcare servers permanently
275
+ Uploadcare::Group.store(group.id)
548
276
  ```
549
277
 
550
- As with files, groups created via UUIDs are not loaded by default.
551
- You need to load the data manually, as it requires a separate
552
- HTTP GET request. New groups created with the `:create_group` method
553
- are loaded by default.
278
+ #### GroupList
279
+ `GroupList` is a list of `Group`
554
280
 
555
281
  ```ruby
556
- @group = @api.group "#{uuid}"
557
-
558
- @group.is_loaded?
559
- # => false
560
-
561
- @group.load_data
562
- # => #<Uploadcare::Api::Group uuid="0d192d66-c7a6-4465-b2cd-46716c5e3df3~2", files_count=2 ...
563
-
564
- # once a group is loaded, you can use any methods described in our API docs
565
- # the files within a loaded group are loaded by default
566
- @group.files
567
- # => [#<Uploadcare::Api::File uuid="24626d2f-3f23-4464-b190-37115ce7742a" ...>,
568
- # ... #{files_count} of them ...
569
- # #<Uploadcare::Api::File uuid="7bb9efa4-05c0-4f36-b0ef-11a4221867f6" ...>]
282
+ @group_list = Uploadcare::GroupList.list
283
+ # To get an array of groups:
284
+ @groups = @group_list.all
570
285
  ```
571
286
 
572
- Check out our docs to learn more about
573
- [groups](https://uploadcare.com/documentation/rest/#group).
574
-
287
+ This is a paginated list, so [pagination](#Pagination) methods apply
575
288
 
576
- ### Group lists
289
+ #### Webhook
290
+ https://uploadcare.com/docs/api_reference/rest/webhooks/
577
291
 
578
- `Uploadcare::Api::GroupList` represents a group collection. It works in a same way as `Uploadcare::Api::FileList` does, but with groups.
292
+ You can use webhooks to provide notifications about your uploads to target urls.
293
+ This gem lets you create and manage webhooks.
579
294
 
580
295
  ```ruby
581
- @list = @api.group_list(limit: 10) # => instance of Uploadcare::Api::GroupList
582
- @list[0] # => instance of Uploadcare::Api::Group
296
+ Uploadcare::Webhook.create(target_url: 'https://example.com/listen', event: 'file.uploaded', is_active: true)
297
+ Uploadcare::Webhook.update(<webhook_id>, target_url: 'https://newexample.com/listen/new', event: 'file.uploaded', is_active: true)
298
+ Uploadcare::Webhook.delete('https://example.com/listen')
299
+ Uploadcare::Webhook.list
583
300
  ```
584
301
 
585
- The only thing that differs is an available options list:
586
-
587
- - **:limit** - Controls page size. Accepts values from 1 to 1000, defaults to 100.
588
- - **:ordering** - Controls the order of returned files. Available values: `datetime_created`, `-datetime_created`. Defaults to `datetime_created`. More info can be found [here](https://uploadcare.com/documentation/rest/#group-groups)
589
- - **:from** - Specifies the starting point for a collection. Resulting collection will contain files from the given value and to the end in a direction set by an **ordering** option. Accepts either a `DateTime` object or an ISO 8601 string. More info can be found [here](https://uploadcare.com/documentation/rest/#group-groups)
590
-
591
-
592
- ### `Project` object
302
+ #### Project
593
303
 
594
- `Project` provides basic info about the connected Uploadcare project.
595
- That object is also an OpenStruct, so every methods out of
596
- [these](https://uploadcare.com/documentation/rest/#project) will work.
304
+ `Project` provides basic info about the connected Uploadcare project. That
305
+ object is also an Hashie::Mash, so every methods out of
306
+ [these](https://uploadcare.com/documentation/rest/#project/?utm_source=github&utm_medium=referral&utm_campaign=uploadcare-ruby) will work.
597
307
 
598
308
  ```ruby
599
- project = @api.project
309
+ @project = Uploadcare::Project.project
600
310
  # => #<Uploadcare::Api::Project collaborators=[], name="demo", pub_key="demopublickey", autostore_enabled=true>
601
311
 
602
- project.name
312
+ @project.name
603
313
  # => "demo"
604
314
 
605
- p.collaborators
315
+ @project.collaborators
606
316
  # => []
607
317
  # while that one was empty, it usually goes like this:
608
318
  # [{"email": collaborator@gmail.com, "name": "Collaborator"}, {"email": collaborator@gmail.com, "name": "Collaborator"}]
609
319
  ```
610
320
 
611
- ### Raw API
321
+ #### Conversion
612
322
 
613
- Raw API is a simple interface allowing you to make
614
- custom requests to Uploadcare REST API.
615
- It's mainly used when you want a low-level control
616
- over your app.
323
+ ##### Video
617
324
 
618
- ```ruby
619
- # here's how you make any requests
620
- @api.request :get, "/files/", {page: 2}
325
+ Uploadcare can encode video files from all popular formats, adjust their quality, format and dimensions, cut out a video fragment, and generate thumbnails via [REST API](https://uploadcare.com/api-refs/rest-api/v0.6.0/).
621
326
 
622
- # and there also are shortcuts for methods
623
- @api.get '/files', {page: 2}
327
+ After each video file upload you obtain a file identifier in UUID format.
328
+ Then you can use this file identifier to convert your video in multiple ways:
624
329
 
625
- @api.post ...
330
+ ```ruby
331
+ Uploadcare::VideoConverter.convert(
332
+ [
333
+ {
334
+ uuid: "dc99200d-9bd6-4b43-bfa9-aa7bfaefca40",
335
+ size: { resize_mode: 'change_ratio', width: '600', height: '400' },
336
+ quality: 'best',
337
+ format: 'ogg',
338
+ cut: { start_time: '0:0:0.0', length: '0:0:1.0' },
339
+ thumbs: { N: 2, number: 1 }
340
+ }
341
+ ], store: false
342
+ )
343
+ ```
344
+ This method accepts options to set properties of an output file:
626
345
 
627
- @api.put ...
346
+ - **uuid** — the file UUID-identifier.
347
+ - **size**:
348
+ - **resize_mode** - size operation to apply to a video file. Can be `preserve_ratio (default)`, `change_ratio`, `scale_crop` or `add_padding`.
349
+ - **width** - width for a converted video.
350
+ - **height** - height for a converted video.
351
+
352
+ ```
353
+ NOTE: you can choose to provide a single dimension (width OR height).
354
+ The value you specify for any of the dimensions should be a non-zero integer divisible by 4
355
+ ```
628
356
 
629
- @api.delete ...
357
+ - **quality** - sets the level of video quality that affects file sizes and hence loading times and volumes of generated traffic. Can be `normal (default)`, `better`, `best`, `lighter`, `lightest`.
358
+ - **format** - format for a converted video. Can be `mp4 (default)`, `webm`, `ogg`.
359
+ - **cut**:
360
+ - **start_time** - defines the starting point of a fragment to cut based on your input file timeline.
361
+ - **length** - defines the duration of that fragment.
362
+ - **thumbs**:
363
+ - **N** - quantity of thumbnails for your video - non-zero integer ranging from 1 to 50; defaults to 1.
364
+ - **number** - zero-based index of a particular thumbnail in a created set, ranging from 1 to (N - 1).
365
+ - **store** - a flag indicating if Uploadcare should store your transformed outputs.
630
366
 
367
+ ```ruby
368
+ # Response
369
+ {
370
+ :result => [
371
+ {
372
+ :original_source=>"dc99200d-9bd6-4b43-bfa9-aa7bfaefca40/video/-/size/600x400/change_ratio/-/quality/best/-/format/ogg/-/cut/0:0:0.0/0:0:1.0/-/thumbs~2/1/",
373
+ :token=>911933811,
374
+ :uuid=>"6f9b88bd-625c-4d60-bfde-145fa3813d95",
375
+ :thumbnails_group_uuid=>"cf34c5a1-8fcc-4db2-9ec5-62c389e84468~2"
376
+ }
377
+ ],
378
+ :problems=>{}
379
+ }
631
380
  ```
381
+ Params in the response:
382
+ - **result** - info related to your transformed output(-s):
383
+ - **original_source** - built path for a particular video with all the conversion operations and parameters.
384
+ - **token** - a processing job token that can be used to get a [job status](https://uploadcare.com/docs/transformations/video-encoding/#status) (see below).
385
+ - **uuid** - UUID of your processed video file.
386
+ - **thumbnails_group_uuid** - holds :uuid-thumb-group, a UUID of a [file group](https://uploadcare.com/api-refs/rest-api/v0.5.0/#operation/groupsList) with thumbnails for an output video, based on the thumbs [operation](https://uploadcare.com/docs/transformations/video-encoding/#operation-thumbs) parameters.
387
+ - **problems** - problems related to your processing job, if any.
632
388
 
633
- All of the raw API methods return a parsed JSON response
634
- or raise an error (handling those is done on your side in the case).
389
+ To convert multiple videos just add params as a hash for each video to the first argument of the `Uploadcare::VideoConverter#convert` method:
635
390
 
636
- ### Error handling
391
+ ```ruby
392
+ Uploadcare::VideoConverter.convert(
393
+ [
394
+ { video_one_params }, { video_two_params }, ...
395
+ ], store: false
396
+ )
397
+ ```
637
398
 
638
- Starting from the version 1.0.2, we've got have custom exceptions
639
- that will be raised in case the Uploadcare service returns
640
- something with 4xx or 5xx HTTP status.
641
399
 
642
- Check out the list of custom errors:
400
+ To check a status of a video processing job you can simply use appropriate method of `Uploadcare::VideoConverter`:
643
401
 
644
402
  ```ruby
645
- 400 => Uploadcare::Error::RequestError::BadRequest,
646
- 401 => Uploadcare::Error::RequestError::Unauthorized,
647
- 403 => Uploadcare::Error::RequestError::Forbidden,
648
- 404 => Uploadcare::Error::RequestError::NotFound,
649
- 406 => Uploadcare::Error::RequestError::NotAcceptable,
650
- 408 => Uploadcare::Error::RequestError::RequestTimeout,
651
- 422 => Uploadcare::Error::RequestError::UnprocessableEntity,
652
- 429 => Uploadcare::Error::RequestError::TooManyRequests,
653
- 500 => Uploadcare::Error::ServerError::InternalServerError,
654
- 502 => Uploadcare::Error::ServerError::BadGateway,
655
- 503 => Uploadcare::Error::ServerError::ServiceUnavailable,
656
- 504 => Uploadcare::Error::ServerError::GatewayTimeout
657
- ```
658
-
659
- That's how you handle a particular error
660
- (in this case, a “404: Not Found” error):
403
+ token = 911933811
404
+ Uploadcare::VideoConverter.status(token)
405
+ ```
406
+ `token` here is a processing job token, obtained in a response of a convert video request.
661
407
 
662
408
  ```ruby
663
- begin
664
- @connection.send :get, '/random_url/', {}
665
- rescue Uploadcare::Error::RequestError::NotFound => e
666
- nil
667
- end
409
+ # Response
410
+ {
411
+ :status => "finished",
412
+ :error => nil,
413
+ :result => {
414
+ :uuid => "dc99200d-9bd6-4b43-bfa9-aa7bfaefca40",
415
+ :thumbnails_group_uuid => "0f181f24-7551-42e5-bebc-14b15d9d3838~2"
416
+ }
417
+ }
668
418
  ```
669
419
 
670
- Handling any request error (covers all 4xx status codes):
420
+ Params in the response:
421
+ - **status** - processing job status, can have one of the following values:
422
+ - *pending* — video file is being prepared for conversion.
423
+ - *processing* — video file processing is in progress.
424
+ - *finished* — the processing is finished.
425
+ - *failed* — we failed to process the video, see error for details.
426
+ - *canceled* — video processing was canceled.
427
+ - **error** - holds a processing error if we failed to handle your video.
428
+ - **result** - repeats the contents of your processing output.
429
+ - **thumbnails_group_uuid** - holds :uuid-thumb-group, a UUID of a file group with thumbnails for an output video, based on the thumbs operation parameters.
430
+ - **uuid** - a UUID of your processed video file.
671
431
 
672
- ```ruby
673
- begin
674
- @connection.send :get, '/random_url/', {}
675
- rescue Uploadcare::Error::RequestError => e
676
- nil
677
- end
678
- ```
432
+ More examples and options can be found [here](https://uploadcare.com/docs/transformations/video-encoding/#video-encoding)
433
+
434
+ ##### Document
679
435
 
680
- Handling any Uploadcare service error:
436
+ Uploadcare allows converting documents to the following target formats: DOC, DOCX, XLS, XLSX, ODT, ODS, RTF, TXT, PDF, JPG, ENHANCED JPG, PNG. Document Conversion works via our [REST API](https://uploadcare.com/api-refs/rest-api/v0.6.0/).
437
+
438
+ After each document file upload you obtain a file identifier in UUID format.
439
+ Then you can use this file identifier to convert your document to a new format:
681
440
 
682
441
  ```ruby
683
- begin
684
- @connection.send :get, '/random_url/', {}
685
- rescue Uploadcare::Error => e
686
- nil
687
- end
442
+ Uploadcare::DocumentConverter.convert(
443
+ [
444
+ {
445
+ uuid: "dc99200d-9bd6-4b43-bfa9-aa7bfaefca40",
446
+ format: 'pdf'
447
+ }
448
+ ], store: false
449
+ )
450
+ ```
451
+ or create an image of a particular page (if using image format):
452
+ ```ruby
453
+ Uploadcare::DocumentConverter.convert(
454
+ [
455
+ {
456
+ uuid: "a4b9db2f-1591-4f4c-8f68-94018924525d",
457
+ format: 'png',
458
+ page: 1
459
+ }
460
+ ], store: false
461
+ )
688
462
  ```
689
463
 
690
- Since many of the above listed things depend on Uploadcare servers,
691
- errors might occasionally occur. Be prepared to handle those.
692
-
693
- ## Testing
464
+ This method accepts options to set properties of an output file:
694
465
 
695
- For testing purposes, run `bundle exec rspec`.
466
+ - **uuid** the file UUID-identifier.
467
+ - **format** - defines the target format you want a source file converted to. The supported values are: `pdf (default)`, `doc`, `docx`, `xls`, `xlsx`, `odt`, `ods`, `rtf`, `txt`, `jpg`, `enhanced.jpg`, `png`. In case the format operation was not found, your input document will be converted to `pdf`.
468
+ - **page** - a page number of a multi-paged document to either `jpg` or `png`. The method will not work for any other target formats.
696
469
 
697
- Please note, if you're willing to run tests using your own keys,
698
- make a `spec/config.yml` file containing the following:
470
+ ```
471
+ NOTE: Use an enhanced.jpg output format for PDF documents with inline fonts.
472
+ When converting multi-page documents to an image format (jpg or png), the output will be a zip archive with one image per page.
473
+ ```
699
474
 
700
- ```yaml
701
- public_key: 'PUBLIC KEY'
702
- private_key: 'PRIVATE KEY'
475
+ ```ruby
476
+ # Response
477
+ {
478
+ :result => [
479
+ {
480
+ :original_source=>"a4b9db2f-1591-4f4c-8f68-94018924525d/document/-/format/png/-/page/1/",
481
+ :token=>21120220
482
+ :uuid=>"88fe5ada-90f1-422a-a233-3a0f3a7cf23c"
483
+ }
484
+ ],
485
+ :problems=>{}
486
+ }
703
487
  ```
488
+ Params in the response:
489
+ - **result** - info related to your transformed output(-s):
490
+ - **original_source** - source file identifier including a target format, if present.
491
+ - **token** - a processing job token that can be used to get a [job status](https://uploadcare.com/docs/transformations/document-conversion/#status) (see below).
492
+ - **uuid** - UUID of your processed document file.
493
+ - **problems** - problems related to your processing job, if any.
704
494
 
705
- ## Contributors
495
+ To convert multiple documents just add params as a hash for each document to the first argument of the `Uploadcare::DocumentConverter#convert` method:
706
496
 
707
- This is open source so fork, hack, request a pull — get a discount.
497
+ ```ruby
498
+ Uploadcare::DocumentConverter.convert(
499
+ [
500
+ { doc_one_params }, { doc_two_params }, ...
501
+ ], store: false
502
+ )
503
+ ```
708
504
 
709
- - [@romanonthego](https://github.com/romanonthego)
710
- - [@vizvamitra](https://github.com/vizvamitra)
711
- - [@dmitry-mukhin](https://github.com/dmitry-mukhin)
712
- - [@zenati](https://github.com/zenati)
713
- - [@renius](https://github.com/renius)
505
+ To check a status of a document processing job you can simply use appropriate method of `Uploadcare::DocumentConverter`:
714
506
 
715
- ## Security issues
507
+ ```ruby
508
+ token = 21120220
509
+ Uploadcare::DocumentConverter.status(token)
510
+ ```
511
+ `token` here is a processing job token, obtained in a response of a convert document request.
716
512
 
717
- If you think you ran into something in Uploadcare libraries
718
- which might have security implications, please hit us up at
719
- [bugbounty@uploadcare.com](mailto:bugbounty@uploadcare.com)
720
- or Hackerone.
513
+ ```ruby
514
+ # Response
515
+ {
516
+ :status => "finished",
517
+ :error => nil,
518
+ :result => {
519
+ :uuid => "a4b9db2f-1591-4f4c-8f68-94018924525d"
520
+ }
521
+ }
522
+ ```
721
523
 
722
- We'll contact you personally in a short time to fix an issue
723
- through co-op and prior to any public disclosure.
524
+ Params in the response:
525
+ - **status** - processing job status, can have one of the following values:
526
+ - *pending* — document file is being prepared for conversion.
527
+ - *processing* — document file processing is in progress.
528
+ - *finished* — the processing is finished.
529
+ - *failed* — we failed to process the document, see error for details.
530
+ - *canceled* — document processing was canceled.
531
+ - **error** - holds a processing error if we failed to handle your document.
532
+ - **result** - repeats the contents of your processing output.
533
+ - **uuid** - a UUID of your processed document file.
534
+
535
+ More examples and options can be found [here](https://uploadcare.com/docs/transformations/document-conversion/#document-conversion)
536
+
537
+ ## Useful links
538
+
539
+ * [Development](https://github.com/uploadcare/uploadcare-ruby/blob/main/DEVELOPMENT.md)
540
+ * [Uploadcare documentation](https://uploadcare.com/docs/?utm_source=github&utm_medium=referral&utm_campaign=uploadcare-ruby)
541
+ * [Upload API reference](https://uploadcare.com/api-refs/upload-api/?utm_source=github&utm_medium=referral&utm_campaign=uploadcare-ruby)
542
+ * [REST API reference](https://uploadcare.com/api-refs/rest-api/?utm_source=github&utm_medium=referral&utm_campaign=uploadcare-ruby)
543
+ * [Changelog](./CHANGELOG.md)
544
+ * [Contributing guide](https://github.com/uploadcare/.github/blob/master/CONTRIBUTING.md)
545
+ * [Security policy](https://github.com/uploadcare/uploadcare-ruby/security/policy)
546
+ * [Support](https://github.com/uploadcare/.github/blob/master/SUPPORT.md)