cloudinary 1.27.0 → 2.3.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.
@@ -0,0 +1,157 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cloudinary
4
+ module Analytics
5
+ extend self
6
+
7
+ QUERY_KEY = '_a'
8
+ ALGO_VERSION = 'B' # The version of the algorithm
9
+ SDK_CODE = 'C' # Cloudinary Ruby SDK
10
+
11
+ @product = 'A' # Official SDK. Set to 'B' for integrations.
12
+ @sdk_code = SDK_CODE
13
+ @sdk_version = Cloudinary::VERSION
14
+ @tech_version = "#{RUBY_VERSION[/\d+\.\d+/]}"
15
+
16
+ CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
17
+ BINARY_PAD_SIZE = 6
18
+
19
+ @char_codes = nil
20
+ @signature = nil
21
+
22
+ # Gets the SDK analytics signature query parameter.
23
+ #
24
+ # @return [String] The SDK signature query parameter.
25
+ def sdk_analytics_query_param
26
+ "#{QUERY_KEY}=#{self.sdk_analytics_signature}"
27
+ end
28
+
29
+ # Gets the SDK signature by encoding the SDK version and tech version.
30
+ #
31
+ # @return [String] The SDK signature.
32
+ def sdk_analytics_signature
33
+ return @signature unless @signature.nil?
34
+
35
+ begin
36
+ @signature = ALGO_VERSION + @product + @sdk_code + encode_version(@sdk_version) + encode_version(@tech_version)
37
+ rescue RangeError
38
+ @signature = 'E'
39
+ end
40
+
41
+ @signature
42
+ end
43
+
44
+ # Sets the product code.
45
+ #
46
+ # Used for integrations.
47
+ #
48
+ # @param [String] product The product code to set. 'A' is for the official SDK. 'B' for integrations.
49
+ #
50
+ # @return [void]
51
+ #
52
+ # @internal
53
+ def product(product)
54
+ @product = product
55
+ end
56
+
57
+ # Sets the SDK code.
58
+ #
59
+ # Used for integrations.
60
+ #
61
+ # @param [String] sdk_code The SDK code to set.
62
+ #
63
+ # @return [void]
64
+ #
65
+ # @internal
66
+ def sdk_code(sdk_code)
67
+ @sdk_code = sdk_code
68
+ end
69
+
70
+ # Sets the SDK version.
71
+ #
72
+ # Used for integrations.
73
+ #
74
+ # @param [String] sdk_version The SDK version to set (MAJOR.MINOR.PATCH), for example: "1.0.0".
75
+ #
76
+ # @return [void]
77
+ #
78
+ # @internal
79
+ def sdk_version(sdk_version)
80
+ @sdk_version = sdk_version
81
+ end
82
+
83
+ # Sets the tech version.
84
+ #
85
+ # Used for integrations.
86
+ #
87
+ # @param [String] tech_version The tech version to set (MAJOR.MINOR), for example: "1.0".
88
+ #
89
+ # @return [void]
90
+ #
91
+ # @internal
92
+ def tech_version(tech_version)
93
+ @tech_version = tech_version.split('.').first(2).join('.')
94
+ end
95
+
96
+ # Encodes a semVer-like version string.
97
+ #
98
+ # Example:
99
+ # input: '1.24.0'
100
+ # explode: ['1','24','0']
101
+ # pad: ['01','24','00']
102
+ # reverse: ['00', '24', '01']
103
+ # implode: '002401'
104
+ # int: 2401
105
+ # binary: '100101100001'
106
+ # padded: '000000100101100001'
107
+ # str_split: ['000000', '100101', '100001']
108
+ # getKey: ['A', 'l', 'h']
109
+ # implode: 'Alh'
110
+ #
111
+ # @param [String] version Can be either x.y.z or x.y
112
+ #
113
+ # @return [String] A string built from 3 characters of the base64 table
114
+ #
115
+ # @raise [RangeError] when version is larger than 43.21.26
116
+ def encode_version(version)
117
+ parts = version.split('.')
118
+
119
+ padded_parts = parts.map { |part| part.rjust(2, '0') }
120
+ number = padded_parts.reverse.join.to_i
121
+ padded_binary = int_to_padded_bin(number, parts.length * BINARY_PAD_SIZE)
122
+
123
+ raise RangeError, 'Version must be smaller than 43.21.26' if padded_binary.length % BINARY_PAD_SIZE != 0
124
+
125
+ encoded_chars = padded_binary.chars.each_slice(BINARY_PAD_SIZE).map { |slice| get_key(slice.join) }
126
+
127
+ encoded_chars.join
128
+ end
129
+
130
+ # Gets the key for binary value.
131
+ #
132
+ # @param [String] binary_value The value.
133
+ #
134
+ # @return [Array, Object] The key for the binary value.
135
+ def get_key(binary_value)
136
+ @char_codes ||= initialize_char_codes
137
+
138
+ @char_codes[binary_value] || ''
139
+ end
140
+
141
+ def initialize_char_codes
142
+ char_codes = {}
143
+ CHARS.chars.each_with_index { |char, idx| char_codes[int_to_padded_bin(idx, BINARY_PAD_SIZE)] = char }
144
+ char_codes
145
+ end
146
+
147
+ # Converts integer to left padded binary string.
148
+ #
149
+ # @param [Integer] integer The input.
150
+ # @param [Integer] pad_num The num of padding chars.
151
+ #
152
+ # @return [String] The padded binary string.
153
+ def int_to_padded_bin(integer, pad_num)
154
+ integer.to_s(2).rjust(pad_num, '0')
155
+ end
156
+ end
157
+ end
@@ -14,6 +14,22 @@ class Cloudinary::Api
14
14
  call_api(:get, "ping", {}, options)
15
15
  end
16
16
 
17
+ # Retrieves account configuration details.
18
+ #
19
+ # @param [Hash] options The optional parameters.
20
+ #
21
+ # @return [Cloudinary::Api::Response]
22
+ #
23
+ # @raise [Cloudinary::Api::Error]
24
+ #
25
+ # @see https://cloudinary.com/documentation/admin_api#config
26
+ def self.config(options={})
27
+ uri = "config"
28
+ params = only(options, :settings)
29
+
30
+ call_api(:get, uri, params, options)
31
+ end
32
+
17
33
  # Gets cloud usage details.
18
34
  #
19
35
  # Returns a report detailing your current Cloudinary cloud usage details, including
@@ -68,7 +84,7 @@ class Cloudinary::Api
68
84
  type = options[:type]
69
85
  uri = "resources/#{resource_type}"
70
86
  uri += "/#{type}" unless type.blank?
71
- call_api(:get, uri, only(options, :next_cursor, :max_results, :prefix, :tags, :context, :moderations, :direction, :start_at, :metadata), options)
87
+ call_api(:get, uri, list_resources_params(options).merge(only(options, :prefix, :start_at)), options)
72
88
  end
73
89
 
74
90
  # Lists assets with the specified tag.
@@ -87,7 +103,7 @@ class Cloudinary::Api
87
103
  def self.resources_by_tag(tag, options={})
88
104
  resource_type = options[:resource_type] || "image"
89
105
  uri = "resources/#{resource_type}/tags/#{tag}"
90
- call_api(:get, uri, only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :metadata), options)
106
+ call_api(:get, uri, list_resources_params(options), options)
91
107
  end
92
108
 
93
109
  # Lists assets currently in the specified moderation queue and status.
@@ -107,7 +123,7 @@ class Cloudinary::Api
107
123
  def self.resources_by_moderation(kind, status, options={})
108
124
  resource_type = options[:resource_type] || "image"
109
125
  uri = "resources/#{resource_type}/moderations/#{kind}/#{status}"
110
- call_api(:get, uri, only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :metadata), options)
126
+ call_api(:get, uri, list_resources_params(options), options)
111
127
  end
112
128
 
113
129
  # Lists assets with the specified contextual metadata.
@@ -129,30 +145,9 @@ class Cloudinary::Api
129
145
  def self.resources_by_context(key, value=nil, options={})
130
146
  resource_type = options[:resource_type] || "image"
131
147
  uri = "resources/#{resource_type}/context"
132
- params = only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :key, :value, :metadata)
133
- params[:key] = key
134
- params[:value] = value
135
- call_api(:get, uri, params, options)
148
+ call_api(:get, uri, list_resources_params(options, :key => key, :value => value), options)
136
149
  end
137
150
 
138
- # Returns the details of the specified asset and all its derived assets by asset id.
139
- #
140
- # Note that if you only need details about the original asset,
141
- # you can also use the Uploader::upload or Uploader::explicit methods, which return the same information and
142
- # are not rate limited.
143
- #
144
- # @param [String] asset_id The Asset ID of the asset.
145
- # @param [Hash] options The optional parameters. See the <a href=https://cloudinary.com/documentation/admin_api#get_the_details_of_a_single_resource target="_blank"> Admin API</a> documentation.
146
- #
147
- # @return [Cloudinary::Api::Response]
148
- #
149
- # @see https://cloudinary.com/documentation/admin_api#get_the_details_of_a_single_resource
150
- def self.resource_by_asset_id(asset_id, options={})
151
- uri = "resources/#{asset_id}"
152
- params = prepare_resource_details_params(options)
153
- call_api(:get, uri, params, options)
154
- end
155
-
156
151
  # Lists assets with the specified public IDs.
157
152
  #
158
153
  # @param [String|Array] public_ids The requested public_ids (up to 100).
@@ -168,7 +163,7 @@ class Cloudinary::Api
168
163
  resource_type = options[:resource_type] || "image"
169
164
  type = options[:type] || "upload"
170
165
  uri = "resources/#{resource_type}/#{type}"
171
- call_api(:get, uri, only(options, :tags, :context, :moderations).merge(:public_ids => public_ids), options)
166
+ call_api(:get, uri, resources_params(options, :public_ids => public_ids), options)
172
167
  end
173
168
 
174
169
  # Lists assets with the specified asset IDs.
@@ -184,9 +179,7 @@ class Cloudinary::Api
184
179
  # @see https://cloudinary.com/documentation/admin_api#get_resources
185
180
  def self.resources_by_asset_ids(asset_ids, options={})
186
181
  uri = "resources/by_asset_ids"
187
- params = only(options, :public_ids, :tags, :moderations, :context)
188
- params[:asset_ids] = asset_ids
189
- call_api(:get, uri, params, options)
182
+ call_api(:get, uri, resources_params(options, :asset_ids => asset_ids), options)
190
183
  end
191
184
 
192
185
  # Returns all assets stored directly in a specified asset folder, regardless of the public ID paths of those assets.
@@ -202,9 +195,7 @@ class Cloudinary::Api
202
195
  # @see https://cloudinary.com/documentation/dynamic_folders#new_admin_api_endpoints
203
196
  def self.resources_by_asset_folder(asset_folder, options={})
204
197
  uri = "resources/by_asset_folder"
205
- params = only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :key, :value, :metadata)
206
- params[:asset_folder] = asset_folder
207
- call_api(:get, uri, params, options)
198
+ call_api(:get, uri, list_resources_params(options, :asset_folder => asset_folder), options)
208
199
  end
209
200
 
210
201
  # Find images based on their visual content.
@@ -216,8 +207,9 @@ class Cloudinary::Api
216
207
  # @raise [Cloudinary::Api::Error]
217
208
  def self.visual_search(options = {})
218
209
  uri = "resources/visual_search"
219
- params = only(options, :image_url, :image_asset_id, :text)
220
- call_api(:get, uri, params, options)
210
+ params = only(options, :image_url, :image_asset_id, :text, :image_file)
211
+ params[:image_file] = Cloudinary::Utils.handle_file_param(params[:image_file]) if params.has_key?(:image_file)
212
+ call_api(:post, uri, params, options)
221
213
  end
222
214
 
223
215
  # Returns the details of the specified asset and all its derived assets.
@@ -242,6 +234,23 @@ class Cloudinary::Api
242
234
  call_api(:get, uri, prepare_resource_details_params(options), options)
243
235
  end
244
236
 
237
+ # Returns the details of the specified asset and all its derived assets by asset id.
238
+ #
239
+ # Note that if you only need details about the original asset,
240
+ # you can also use the Uploader::upload or Uploader::explicit methods, which return the same information and
241
+ # are not rate limited.
242
+ #
243
+ # @param [String] asset_id The Asset ID of the asset.
244
+ # @param [Hash] options The optional parameters. See the <a href=https://cloudinary.com/documentation/admin_api#get_the_details_of_a_single_resource target="_blank"> Admin API</a> documentation.
245
+ #
246
+ # @return [Cloudinary::Api::Response]
247
+ #
248
+ # @see https://cloudinary.com/documentation/admin_api#get_the_details_of_a_single_resource
249
+ def self.resource_by_asset_id(asset_id, options={})
250
+ uri = "resources/#{asset_id}"
251
+ call_api(:get, uri, prepare_resource_details_params(options), options)
252
+ end
253
+
245
254
  # Reverts to the latest backed up version of the specified deleted assets.
246
255
  #
247
256
  # @param [String|Array] public_ids The public IDs of the backed up assets to restore. They can be existing or
@@ -656,7 +665,7 @@ class Cloudinary::Api
656
665
  #
657
666
  # @see https://cloudinary.com/documentation/admin_api#update_an_upload_preset
658
667
  def self.update_upload_preset(name, options={})
659
- params = Cloudinary::Uploader.build_upload_params(options)
668
+ params = Cloudinary::Uploader.build_upload_params(options, true)
660
669
  call_api(:put, "upload_presets/#{name}", params.merge(only(options, :unsigned, :disallow_public_id, :live)), options)
661
670
  end
662
671
 
@@ -671,7 +680,7 @@ class Cloudinary::Api
671
680
  #
672
681
  # @see https://cloudinary.com/documentation/admin_api#create_an_upload_preset
673
682
  def self.create_upload_preset(options={})
674
- params = Cloudinary::Uploader.build_upload_params(options)
683
+ params = Cloudinary::Uploader.build_upload_params(options, true)
675
684
  call_api(:post, "upload_presets", params.merge(only(options, :name, :unsigned, :disallow_public_id, :live)), options)
676
685
  end
677
686
 
@@ -738,6 +747,21 @@ class Cloudinary::Api
738
747
  call_api(:post, "folders/#{folder_name}", {}, options)
739
748
  end
740
749
 
750
+ # Renames existing asset folder.
751
+ #
752
+ # @param [String] from_path The full path of an existing asset folder.
753
+ # @param [String] to_path The full path of the new asset folder.
754
+ # @param [Hash] options The optional parameters.
755
+ #
756
+ # @return [Cloudinary::Api::Response]
757
+ #
758
+ # @raise [Cloudinary::Api::Error]
759
+ #
760
+ # @see https://cloudinary.com/documentation/admin_api#rename_folder
761
+ def self.rename_folder(from_path, to_path, options={})
762
+ call_api(:put, "folders/#{from_path}", {:to_folder => to_path}, options)
763
+ end
764
+
741
765
  # Lists upload mappings by folder and its mapped template (URL).
742
766
  #
743
767
  # @param [Hash] options The optional parameters. See the
@@ -1013,9 +1037,7 @@ class Cloudinary::Api
1013
1037
  #
1014
1038
  # @see https://cloudinary.com/documentation/admin_api#create_a_metadata_field
1015
1039
  def self.add_metadata_field(field, options = {})
1016
- params = only(field, :type, :external_id, :label, :mandatory, :default_value, :validation, :datasource)
1017
-
1018
- call_metadata_api(:post, [], params, options)
1040
+ call_metadata_api(:post, [], prepare_metadata_field_params(field), options)
1019
1041
  end
1020
1042
 
1021
1043
  # Updates a metadata field by external ID.
@@ -1032,10 +1054,19 @@ class Cloudinary::Api
1032
1054
  #
1033
1055
  # @see https://cloudinary.com/documentation/admin_api#update_a_metadata_field_by_external_id
1034
1056
  def self.update_metadata_field(field_external_id, field, options = {})
1035
- uri = [field_external_id]
1036
- params = only(field, :label, :mandatory, :default_value, :validation)
1057
+ uri = [field_external_id]
1037
1058
 
1038
- call_metadata_api(:put, uri, params, options)
1059
+ call_metadata_api(:put, uri, prepare_metadata_field_params(field), options)
1060
+ end
1061
+
1062
+ # Prepares optional parameters for add/update_metadata_field API calls.
1063
+ # @param [Hash] options Additional options
1064
+ # @return [Object] Optional parameters
1065
+ def self.prepare_metadata_field_params(field)
1066
+ only(field,
1067
+ :type, :external_id, :label, :mandatory, :restrictions, :default_value, :default_disabled,
1068
+ :validation, :datasource, :allow_dynamic_list_values
1069
+ )
1039
1070
  end
1040
1071
 
1041
1072
  # Deletes a metadata field definition by external ID.
@@ -1229,6 +1260,25 @@ class Cloudinary::Api
1229
1260
  call_metadata_rules_api(:delete, uri, {}, options)
1230
1261
  end
1231
1262
 
1263
+ # Analyzes an asset with the requested analysis type.
1264
+ #
1265
+ # @param [Object] input_type The type of input for the asset to analyze ('uri').
1266
+ # @param [Object] analysis_type The type of analysis to run ('google_tagging', 'captioning', 'fashion').
1267
+ # @param [Hash] options The optional parameters.
1268
+ #
1269
+ # @return [Cloudinary::Api::Response]
1270
+ #
1271
+ # @raise [Cloudinary::Api::Error]
1272
+ def self.analyze(input_type, analysis_type, options = {})
1273
+ api_uri = ["analysis", "analyze", input_type]
1274
+ params = only(options, :uri, :parameters)
1275
+ params["analysis_type"] = analysis_type
1276
+
1277
+ options[:api_version] = 'v2'
1278
+
1279
+ call_api(:post, api_uri, params, options)
1280
+ end
1281
+
1232
1282
  protected
1233
1283
 
1234
1284
  # Execute a call api for input params.
@@ -1243,13 +1293,14 @@ class Cloudinary::Api
1243
1293
  api_key = options[:api_key] || Cloudinary.config.api_key
1244
1294
  api_secret = options[:api_secret] || Cloudinary.config.api_secret
1245
1295
  oauth_token = options[:oauth_token] || Cloudinary.config.oauth_token
1296
+ api_version = options[:api_version] || Cloudinary.config.api_version || 'v1_1'
1246
1297
 
1247
1298
  validate_authorization(api_key, api_secret, oauth_token)
1248
1299
 
1249
1300
  auth = { :key => api_key, :secret => api_secret, :oauth_token => oauth_token }
1250
1301
 
1251
1302
  call_cloudinary_api(method, uri, auth, params, options) do |cloudinary, inner_uri|
1252
- [cloudinary, 'v1_1', cloud_name, inner_uri]
1303
+ [cloudinary, api_version, cloud_name, inner_uri]
1253
1304
  end
1254
1305
  end
1255
1306
 
@@ -1261,7 +1312,7 @@ class Cloudinary::Api
1261
1312
  return Cloudinary::Utils.json_decode(response.body)
1262
1313
  rescue => e
1263
1314
  # Error is parsing json
1264
- raise GeneralError.new("Error parsing server response (#{response.code}) - #{response.body}. Got - #{e}")
1315
+ raise GeneralError.new("Error parsing server response (#{response.status}) - #{response.body}. Got - #{e}")
1265
1316
  end
1266
1317
 
1267
1318
  # Protected function that assists with performing an API call to the metadata_fields part of the Admin API.
@@ -1398,4 +1449,19 @@ class Cloudinary::Api
1398
1449
  params[by_key] = value
1399
1450
  call_api("post", "resources/#{resource_type}/#{type}/update_access_mode", params, options)
1400
1451
  end
1452
+
1453
+ private
1454
+
1455
+ RESOURCES_PARAMS = [:tags, :context, :metadata, :moderations, :fields].freeze
1456
+ LIST_RESOURCES_PARAMS = [:next_cursor, :max_results, :direction].freeze
1457
+
1458
+ def self.resources_params(options, params = {})
1459
+ params.merge!(only(options, *RESOURCES_PARAMS))
1460
+ params[:fields] = Cloudinary::Utils.build_array(options[:fields]).join(",") unless params[:fields].nil?
1461
+ params
1462
+ end
1463
+
1464
+ def self.list_resources_params(options, params = {})
1465
+ params.merge(resources_params(options)).merge!(only(options, *LIST_RESOURCES_PARAMS))
1466
+ end
1401
1467
  end
@@ -1,11 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'openssl'
4
- if RUBY_VERSION > "2"
5
- require "ostruct"
6
- else
7
- require "cloudinary/ostruct2"
8
- end
4
+ require "ostruct"
9
5
 
10
6
 
11
7
  module Cloudinary
@@ -1,7 +1,8 @@
1
- require "rest_client"
1
+ require "faraday"
2
2
  require "json"
3
3
 
4
4
  module Cloudinary::BaseApi
5
+ @adapter = nil
5
6
  class Error < CloudinaryException; end
6
7
  class NotFound < Error; end
7
8
  class NotAllowed < Error; end
@@ -15,17 +16,19 @@ module Cloudinary::BaseApi
15
16
  attr_reader :rate_limit_reset_at, :rate_limit_remaining, :rate_limit_allowed
16
17
 
17
18
  def initialize(response=nil)
18
- if response
19
- # This sets the instantiated self as the response Hash
20
- update Cloudinary::Api.parse_json_response response
19
+ unless response
20
+ return
21
+ end
21
22
 
22
- # According to RFC 2616, header names are case-insensitive.
23
- lc_headers = response.headers.transform_keys(&:downcase)
23
+ # This sets the instantiated self as the response Hash
24
+ update Cloudinary::Api.parse_json_response response
24
25
 
25
- @rate_limit_allowed = lc_headers[:x_featureratelimit_limit].to_i if lc_headers[:x_featureratelimit_limit]
26
- @rate_limit_reset_at = Time.parse(lc_headers[:x_featureratelimit_reset]) if lc_headers[:x_featureratelimit_reset]
27
- @rate_limit_remaining = lc_headers[:x_featureratelimit_remaining].to_i if lc_headers[:x_featureratelimit_remaining]
28
- end
26
+ # According to RFC 2616, header names are case-insensitive.
27
+ lc_headers = response.headers.transform_keys(&:downcase)
28
+
29
+ @rate_limit_allowed = lc_headers["x-featureratelimit-limit"].to_i if lc_headers["x-featureratelimit-limit"]
30
+ @rate_limit_reset_at = Time.parse(lc_headers["x-featureratelimit-reset"]) if lc_headers["x-featureratelimit-reset"]
31
+ @rate_limit_remaining = lc_headers["x-featureratelimit-remaining"].to_i if lc_headers["x-featureratelimit-remaining"]
29
32
  end
30
33
  end
31
34
 
@@ -36,28 +39,30 @@ module Cloudinary::BaseApi
36
39
  end
37
40
 
38
41
  def call_json_api(method, api_url, payload, timeout, headers, proxy = nil, user = nil, password = nil)
39
- RestClient::Request.execute(method: method,
40
- url: api_url,
41
- payload: payload,
42
- timeout: timeout,
43
- headers: headers,
44
- proxy: proxy,
45
- user: user,
46
- password: password) do |response|
47
- return Response.new(response) if response.code == 200
48
- exception_class = case response.code
49
- when 400 then BadRequest
50
- when 401 then AuthorizationRequired
51
- when 403 then NotAllowed
52
- when 404 then NotFound
53
- when 409 then AlreadyExists
54
- when 420 then RateLimited
55
- when 500 then GeneralError
56
- else raise GeneralError.new("Server returned unexpected status code - #{response.code} - #{response.body}")
57
- end
58
- json = Cloudinary::Api.parse_json_response(response)
59
- raise exception_class.new(json["error"]["message"])
42
+ conn = Faraday.new(url: api_url) do |faraday|
43
+ faraday.proxy = proxy if proxy
44
+ faraday.request :json
45
+ faraday.adapter @adapter || Faraday.default_adapter
60
46
  end
47
+
48
+ response = conn.run_request(method.downcase.to_sym, nil, payload, headers) do |req|
49
+ req.options.timeout = timeout if timeout
50
+ req.basic_auth(user, password) if user && password
51
+ end
52
+
53
+ return Response.new(response) if response.status == 200
54
+ exception_class = case response.status
55
+ when 400 then BadRequest
56
+ when 401 then AuthorizationRequired
57
+ when 403 then NotAllowed
58
+ when 404 then NotFound
59
+ when 409 then AlreadyExists
60
+ when 420, 429 then RateLimited
61
+ when 500 then GeneralError
62
+ else raise GeneralError.new("Server returned unexpected status code - #{response.status} - #{response.body}")
63
+ end
64
+ json = Cloudinary::Api.parse_json_response(response)
65
+ raise exception_class.new(json["error"]["message"])
61
66
  end
62
67
 
63
68
  private
@@ -36,7 +36,8 @@ class Cloudinary::CarrierWave::Storage < ::CarrierWave::Storage::Abstract
36
36
  params[:type]=uploader.class.storage_type
37
37
 
38
38
  params[:resource_type] ||= :auto
39
- uploader.metadata = Cloudinary::Uploader.upload(data, params)
39
+ upload_method = uploader.respond_to?(:upload_chunked?) && uploader.upload_chunked? ? "upload_large" : "upload"
40
+ uploader.metadata = Cloudinary::Uploader.send(upload_method, data, params)
40
41
  if uploader.metadata["error"]
41
42
  raise Cloudinary::CarrierWave::UploadError.new(uploader.metadata["error"]["message"], uploader.metadata["error"]["http_code"])
42
43
  end
@@ -82,14 +83,7 @@ class Cloudinary::CarrierWave::Storage < ::CarrierWave::Storage::Abstract
82
83
  end
83
84
 
84
85
  if defined?(ActiveRecord::Base) && uploader.model.is_a?(ActiveRecord::Base)
85
- primary_key = model_class.primary_key.to_sym
86
- if defined?(::ActiveRecord::VERSION::MAJOR) && ::ActiveRecord::VERSION::MAJOR > 2
87
- model_class.where(primary_key=>uploader.model.send(primary_key)).update_all(column=>name)
88
- else
89
- # Removed since active record version 3.0.0
90
- model_class.update_all({column=>name}, {primary_key=>uploader.model.send(primary_key)})
91
- end
92
- uploader.model.send :write_attribute, column, name
86
+ uploader.model.update_column(column, name)
93
87
  elsif defined?(Mongoid::Document) && uploader.model.is_a?(Mongoid::Document)
94
88
  # Mongoid support
95
89
  if Mongoid::VERSION.split(".").first.to_i >= 4
@@ -192,11 +192,6 @@ module Cloudinary::CarrierWave
192
192
 
193
193
  end
194
194
 
195
- # @deprecated
196
- def self.split_format(identifier)
197
- return Cloudinary::PreloadedFile.split_format(identifier)
198
- end
199
-
200
195
  def default_format
201
196
  "png"
202
197
  end
@@ -179,7 +179,7 @@ module CloudinaryHelper
179
179
  version_store = options.delete(:version_store)
180
180
  if options[:version].blank? && (version_store == :file) && defined?(Rails) && defined?(Rails.root)
181
181
  file_name = "#{Rails.root}/tmp/cloudinary/cloudinary_sprite_#{source.sub(/\..*/, '')}.version"
182
- if File.exists?(file_name)
182
+ if File.exist?(file_name)
183
183
  options[:version] = File.read(file_name).chomp
184
184
  end
185
185
  end
@@ -286,13 +286,6 @@ module CloudinaryHelper
286
286
  Cloudinary::Utils.private_download_url(public_id, format, options)
287
287
  end
288
288
 
289
- # Helper method that uses the deprecated ZIP download API.
290
- # Replaced by cl_download_zip_url that uses the more advanced and robust archive generation and download API
291
- # @deprecated
292
- def cl_zip_download_url(tag, options = {})
293
- Cloudinary::Utils.zip_download_url(tag, options)
294
- end
295
-
296
289
  # @see {Cloudinary::Utils.download_archive_url}
297
290
  def cl_download_archive_url(options = {})
298
291
  Cloudinary::Utils.download_archive_url(options)
@@ -304,13 +297,13 @@ module CloudinaryHelper
304
297
  end
305
298
 
306
299
  def cl_signed_download_url(public_id, options = {})
307
- Cloudinary::Utils.signed_download_url(public_id, options)
300
+ Cloudinary::Utils.cloudinary_url(public_id, options)
308
301
  end
309
302
 
310
303
  def self.included(base)
311
304
  ActionView::Helpers::FormBuilder.send(:include, Cloudinary::FormBuilder)
312
305
  base.class_eval do
313
- if !method_defined?(:image_tag)
306
+ unless method_defined?(:image_tag)
314
307
  include ActionView::Helpers::AssetTagHelper
315
308
  end
316
309
  alias_method :image_tag_without_cloudinary, :image_tag unless public_method_defined? :image_tag_without_cloudinary
@@ -325,7 +318,6 @@ module CloudinaryHelper
325
318
  private
326
319
 
327
320
  def cloudinary_url_internal(source, options = {})
328
- options[:ssl_detected] = request.ssl? if defined?(request) && request && request.respond_to?(:ssl?)
329
321
  if defined?(CarrierWave::Uploader::Base) && source.is_a?(CarrierWave::Uploader::Base)
330
322
  if source.version_name.present?
331
323
  options[:transformation] = Cloudinary::Utils.build_array(source.transformation) + Cloudinary::Utils.build_array(options[:transformation])