cloudinary 1.27.0 → 1.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46b21a3d7dd2411acaaeb35016f2ff7b648aeae5c1d077870f38e858ce1abedf
4
- data.tar.gz: 5825bea0988e97e71df1d93fde04739b502230cda987f90415cb46f55df8b6b7
3
+ metadata.gz: 0ec56a8224fa9a3318d7e0d3e7ce7747c888767a4b365a752310e38b7747f4a3
4
+ data.tar.gz: 58f0148449592fb70e8a87bc292ddeea43a09b0f879fca9c62c1594b3ff487cc
5
5
  SHA512:
6
- metadata.gz: 24c1334398c9c24ce9b0b536e991fb76aa633e1bda93b5e8dcccc1d2ac2f747e4645f52b61ad3b6db7bb9a59a092df602c35b964a05661c151fb6026cd1954c0
7
- data.tar.gz: f8f3cdbe7b7374532f5dae2f5dca3543697a2fb2398050b4a7874d6527b3e87ffc84970684aefe25c65f255ba9ec89e15470e28658c28287df781e4ee2144799
6
+ metadata.gz: 44e6c4cefaebd3853f8da9c40123d05205b6fa57fd58eb22e1a8a419bad658b3184eb2bd068f79b8d54601793295c333e6a02720d6a5bdbcb699b234432603e2
7
+ data.tar.gz: de7032533e031e15c51ccc17ff8e77a2aabc6f9aea4958a58d2313b30aeadc8b14574e36090c99a9e58788e3a376bc9330cfdd0e8d77fcb96d3d4deea7cbfd57
data/.travis.yml CHANGED
@@ -1,22 +1,17 @@
1
- dist: focal
1
+ dist: jammy
2
2
  language: ruby
3
3
  rvm:
4
- - 2.6.7
5
- - 2.7.4
6
- - 3.0.2
4
+ - 2.7.8
5
+ - 3.1.4
6
+ - 3.2.2
7
+ - 3.3.0
7
8
 
8
9
  matrix:
9
10
  include:
10
- - name: "Ruby 1.9"
11
- dist: precise
12
- rvm: 1.9.3
13
- before_install:
14
- - gem install bundler -v 1.17.3
15
- - name: "Ruby 2.5.9"
16
- dist: xenial
17
- rvm: ruby-2.5.9
18
- before_install:
19
- - gem install bundler -v 2.3.26
11
+ # There is an OpenSSL issue on Jammy with Ruby 3.0
12
+ - name: "Ruby: 3.0.6"
13
+ dist: focal
14
+ rvm: 3.0.6
20
15
 
21
16
  before_script: >
22
17
  export CLOUDINARY_URL=$(bash tools/get_test_cloud.sh);
data/CHANGELOG.md CHANGED
@@ -1,3 +1,35 @@
1
+ 1.29.0 / 2024-02-26
2
+ ==================
3
+
4
+ New functionality and features
5
+ ------------------------------
6
+
7
+ * Add support for `context` parameter in `url_for_direct_upload`
8
+ * Add support for `use_fetch_format` parameter in `cl_video_tag`
9
+ * Add support for `fields` parameter in Search and Admin APIs
10
+ * Add support for access keys management in Account Provisioning API
11
+
12
+ Other Changes
13
+ -------------
14
+
15
+ * Avoid early loading of `ActionView::Base`
16
+ * Fix `sqlite3` dependency version
17
+ * Add Rails 7.x to supported versions on `README.md`
18
+
19
+ 1.28.0 / 2023-11-06
20
+ ==================
21
+
22
+ New functionality and features
23
+ ------------------------------
24
+
25
+ * Add support for `image_file` parameter in `visual_search` Admin API
26
+ * Add support for `on_success` upload parameter
27
+
28
+ Other Changes
29
+ -------------
30
+
31
+ * Replace `update_all` to `update_column` in CarrierWave storage
32
+
1
33
  1.27.0 / 2023-07-31
2
34
  ==================
3
35
 
data/README.md CHANGED
@@ -42,9 +42,9 @@ the [Ruby on Rails SDK Guide](https://cloudinary.com/documentation/rails_integra
42
42
  |-------------|------------|----------|----------|
43
43
  | 1.x | v | v | v |
44
44
 
45
- | SDK Version | Rails 5.x | Rails 6.x |
46
- |-------------|-----------|-----------|
47
- | 1.x | v | v |
45
+ | SDK Version | Rails 5.x | Rails 6.x | Rails 7.x |
46
+ |-------------|-----------|-----------|-----------|
47
+ | 1.x | v | v | v |
48
48
 
49
49
  ## Installation
50
50
 
data/cloudinary.gemspec CHANGED
@@ -39,7 +39,7 @@ Gem::Specification.new do |s|
39
39
  else
40
40
  s.add_development_dependency "rake", "<= 12.2.1"
41
41
  end
42
- if RUBY_VERSION >= "2.7.0"
42
+ if RUBY_VERSION >= "3.0.0"
43
43
  s.add_development_dependency "sqlite3"
44
44
  else
45
45
  s.add_development_dependency "sqlite3", "< 1.6.0"
@@ -81,7 +81,9 @@ module ActiveStorage
81
81
  # through direct upload (client side js), filename is missing, and that leads to inconsistent/broken URLs.
82
82
  # To avoid that, we explicitly pass file format in options.
83
83
  options[:format] = ext_for_file(key) if options[:resource_type] == "raw"
84
+ context = options.delete(:context)
84
85
  options[:context] = {active_storage_key: key}
86
+ options[:context].reverse_merge!(context) if context.respond_to?(:merge)
85
87
  options.delete(:file)
86
88
  payload[:url] = api_uri("upload", options)
87
89
  end
@@ -13,10 +13,10 @@ class Cloudinary::AccountApi
13
13
  # @param [Object] options additional options
14
14
  def self.create_sub_account(name, cloud_name = nil, custom_attributes = {}, enabled = nil, base_account = nil, options = {})
15
15
  params = {
16
- name: name,
17
- cloud_name: cloud_name,
18
- custom_attributes: custom_attributes,
19
- enabled: enabled,
16
+ name: name,
17
+ cloud_name: cloud_name,
18
+ custom_attributes: custom_attributes,
19
+ enabled: enabled,
20
20
  base_sub_account_id: base_account
21
21
  }
22
22
 
@@ -35,10 +35,10 @@ class Cloudinary::AccountApi
35
35
  # @param [Object] options additional options
36
36
  def self.update_sub_account(sub_account_id, name = nil, cloud_name = nil, custom_attributes = nil, enabled = nil, options = {})
37
37
  params = {
38
- name: name,
39
- cloud_name: cloud_name,
38
+ name: name,
39
+ cloud_name: cloud_name,
40
40
  custom_attributes: custom_attributes,
41
- enabled: enabled
41
+ enabled: enabled
42
42
  }
43
43
 
44
44
  call_account_api(:put, ['sub_accounts', sub_account_id], params, options.merge(content_type: :json))
@@ -53,8 +53,8 @@ class Cloudinary::AccountApi
53
53
  def self.sub_accounts(enabled = nil, ids = [], prefix = nil, options = {})
54
54
  params = {
55
55
  enabled: enabled,
56
- ids: ids,
57
- prefix: prefix
56
+ ids: ids,
57
+ prefix: prefix
58
58
  }
59
59
 
60
60
  call_account_api(:get, 'sub_accounts', params, options.merge(content_type: :json))
@@ -84,9 +84,9 @@ class Cloudinary::AccountApi
84
84
  # @param [Object] options additional options
85
85
  def self.create_user(name, email, role, sub_account_ids = [], options = {})
86
86
  params = {
87
- name: name,
88
- email: email,
89
- role: role,
87
+ name: name,
88
+ email: email,
89
+ role: role,
90
90
  sub_account_ids: sub_account_ids
91
91
  }
92
92
 
@@ -111,9 +111,9 @@ class Cloudinary::AccountApi
111
111
  # @param [Object] options additional options
112
112
  def self.update_user(user_id, name = nil, email = nil, role = nil, sub_account_ids = nil, options = {})
113
113
  params = {
114
- name: name,
115
- email: email,
116
- role: role,
114
+ name: name,
115
+ email: email,
116
+ role: role,
117
117
  sub_account_ids: sub_account_ids
118
118
  }
119
119
 
@@ -135,10 +135,10 @@ class Cloudinary::AccountApi
135
135
  # @param [Object] options additional options
136
136
  def self.users(pending = nil, user_ids = [], prefix = nil, sub_account_id = nil, options = {})
137
137
  params = {
138
- ids: user_ids,
139
- prefix: prefix,
138
+ ids: user_ids,
139
+ prefix: prefix,
140
140
  sub_account_id: sub_account_id,
141
- pending: pending
141
+ pending: pending
142
142
  }
143
143
 
144
144
  call_account_api(:get, 'users', params, options.merge(content_type: :json))
@@ -210,6 +210,44 @@ class Cloudinary::AccountApi
210
210
  call_account_api(:get, ['user_groups', group_id, 'users'], {}, options.merge(content_type: :json))
211
211
  end
212
212
 
213
+ # Lists access keys.
214
+ #
215
+ # @param [String] sub_account_id The ID of the sub-account.
216
+ # @param [Object] options Additional options.
217
+ def self.access_keys(sub_account_id, options = {})
218
+ params = Cloudinary::Api.only(options, :page_size, :page, :sort_by, :sort_order)
219
+ call_account_api(:get, ['sub_accounts', sub_account_id, 'access_keys'], params, options)
220
+ end
221
+
222
+ # Generates access key.
223
+ #
224
+ # @param [String] sub_account_id The ID of the sub-account.
225
+ # @param [String] name The display name as shown in the management console.
226
+ # @param [Boolean] enabled Whether to create the access key as enabled (default is enabled).
227
+ # @param [Object] options Additional options.
228
+ def self.generate_access_key(sub_account_id, name = nil, enabled = nil, options = {})
229
+ params = {
230
+ name: name,
231
+ enabled: enabled,
232
+ }
233
+ call_account_api(:post, ['sub_accounts', sub_account_id, 'access_keys'], params, options.merge(content_type: :json))
234
+ end
235
+
236
+ # Updates access key.
237
+ #
238
+ # @param [String] sub_account_id The ID of the sub-account.
239
+ # @param [String] api_key The API key.
240
+ # @param [String] name The display name as shown in the management console.
241
+ # @param [Boolean] enabled Enable or disable the access key.
242
+ # @param [Object] options Additional options.
243
+ def self.update_access_key(sub_account_id, api_key, name = nil, enabled = nil, options = {})
244
+ params = {
245
+ name: name,
246
+ enabled: enabled,
247
+ }
248
+ call_account_api(:put, ['sub_accounts', sub_account_id, 'access_keys', api_key], params, options.merge(content_type: :json))
249
+ end
250
+
213
251
  def self.call_account_api(method, uri, params, options)
214
252
  account_id = options[:account_id] || Cloudinary.account_config.account_id || raise('Must supply account_id')
215
253
  api_key = options[:provisioning_api_key] || Cloudinary.account_config.provisioning_api_key || raise('Must supply provisioning api_key')
@@ -68,7 +68,7 @@ class Cloudinary::Api
68
68
  type = options[:type]
69
69
  uri = "resources/#{resource_type}"
70
70
  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)
71
+ call_api(:get, uri, list_resources_params(options).merge(only(options, :prefix, :start_at)), options)
72
72
  end
73
73
 
74
74
  # Lists assets with the specified tag.
@@ -87,7 +87,7 @@ class Cloudinary::Api
87
87
  def self.resources_by_tag(tag, options={})
88
88
  resource_type = options[:resource_type] || "image"
89
89
  uri = "resources/#{resource_type}/tags/#{tag}"
90
- call_api(:get, uri, only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :metadata), options)
90
+ call_api(:get, uri, list_resources_params(options), options)
91
91
  end
92
92
 
93
93
  # Lists assets currently in the specified moderation queue and status.
@@ -107,7 +107,7 @@ class Cloudinary::Api
107
107
  def self.resources_by_moderation(kind, status, options={})
108
108
  resource_type = options[:resource_type] || "image"
109
109
  uri = "resources/#{resource_type}/moderations/#{kind}/#{status}"
110
- call_api(:get, uri, only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :metadata), options)
110
+ call_api(:get, uri, list_resources_params(options), options)
111
111
  end
112
112
 
113
113
  # Lists assets with the specified contextual metadata.
@@ -129,30 +129,9 @@ class Cloudinary::Api
129
129
  def self.resources_by_context(key, value=nil, options={})
130
130
  resource_type = options[:resource_type] || "image"
131
131
  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)
132
+ call_api(:get, uri, list_resources_params(options, :key => key, :value => value), options)
136
133
  end
137
134
 
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
135
  # Lists assets with the specified public IDs.
157
136
  #
158
137
  # @param [String|Array] public_ids The requested public_ids (up to 100).
@@ -168,7 +147,7 @@ class Cloudinary::Api
168
147
  resource_type = options[:resource_type] || "image"
169
148
  type = options[:type] || "upload"
170
149
  uri = "resources/#{resource_type}/#{type}"
171
- call_api(:get, uri, only(options, :tags, :context, :moderations).merge(:public_ids => public_ids), options)
150
+ call_api(:get, uri, resources_params(options, :public_ids => public_ids), options)
172
151
  end
173
152
 
174
153
  # Lists assets with the specified asset IDs.
@@ -184,9 +163,7 @@ class Cloudinary::Api
184
163
  # @see https://cloudinary.com/documentation/admin_api#get_resources
185
164
  def self.resources_by_asset_ids(asset_ids, options={})
186
165
  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)
166
+ call_api(:get, uri, resources_params(options, :asset_ids => asset_ids), options)
190
167
  end
191
168
 
192
169
  # Returns all assets stored directly in a specified asset folder, regardless of the public ID paths of those assets.
@@ -202,9 +179,7 @@ class Cloudinary::Api
202
179
  # @see https://cloudinary.com/documentation/dynamic_folders#new_admin_api_endpoints
203
180
  def self.resources_by_asset_folder(asset_folder, options={})
204
181
  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)
182
+ call_api(:get, uri, list_resources_params(options, :asset_folder => asset_folder), options)
208
183
  end
209
184
 
210
185
  # Find images based on their visual content.
@@ -216,8 +191,9 @@ class Cloudinary::Api
216
191
  # @raise [Cloudinary::Api::Error]
217
192
  def self.visual_search(options = {})
218
193
  uri = "resources/visual_search"
219
- params = only(options, :image_url, :image_asset_id, :text)
220
- call_api(:get, uri, params, options)
194
+ params = only(options, :image_url, :image_asset_id, :text, :image_file)
195
+ params[:image_file] = Cloudinary::Utils.handle_file_param(params[:image_file]) if params.has_key?(:image_file)
196
+ call_api(:post, uri, params, options)
221
197
  end
222
198
 
223
199
  # Returns the details of the specified asset and all its derived assets.
@@ -242,6 +218,23 @@ class Cloudinary::Api
242
218
  call_api(:get, uri, prepare_resource_details_params(options), options)
243
219
  end
244
220
 
221
+ # Returns the details of the specified asset and all its derived assets by asset id.
222
+ #
223
+ # Note that if you only need details about the original asset,
224
+ # you can also use the Uploader::upload or Uploader::explicit methods, which return the same information and
225
+ # are not rate limited.
226
+ #
227
+ # @param [String] asset_id The Asset ID of the asset.
228
+ # @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.
229
+ #
230
+ # @return [Cloudinary::Api::Response]
231
+ #
232
+ # @see https://cloudinary.com/documentation/admin_api#get_the_details_of_a_single_resource
233
+ def self.resource_by_asset_id(asset_id, options={})
234
+ uri = "resources/#{asset_id}"
235
+ call_api(:get, uri, prepare_resource_details_params(options), options)
236
+ end
237
+
245
238
  # Reverts to the latest backed up version of the specified deleted assets.
246
239
  #
247
240
  # @param [String|Array] public_ids The public IDs of the backed up assets to restore. They can be existing or
@@ -1398,4 +1391,19 @@ class Cloudinary::Api
1398
1391
  params[by_key] = value
1399
1392
  call_api("post", "resources/#{resource_type}/#{type}/update_access_mode", params, options)
1400
1393
  end
1394
+
1395
+ private
1396
+
1397
+ RESOURCES_PARAMS = [:tags, :context, :metadata, :moderations, :fields].freeze
1398
+ LIST_RESOURCES_PARAMS = [:next_cursor, :max_results, :direction].freeze
1399
+
1400
+ def self.resources_params(options, params = {})
1401
+ params.merge!(only(options, *RESOURCES_PARAMS))
1402
+ params[:fields] = Cloudinary::Utils.build_array(options[:fields]).join(",") unless params[:fields].nil?
1403
+ params
1404
+ end
1405
+
1406
+ def self.list_resources_params(options, params = {})
1407
+ params.merge(resources_params(options)).merge!(only(options, *LIST_RESOURCES_PARAMS))
1408
+ end
1401
1409
  end
@@ -82,14 +82,7 @@ class Cloudinary::CarrierWave::Storage < ::CarrierWave::Storage::Abstract
82
82
  end
83
83
 
84
84
  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
85
+ uploader.model.update_column(column, name)
93
86
  elsif defined?(Mongoid::Document) && uploader.model.is_a?(Mongoid::Document)
94
87
  # Mongoid support
95
88
  if Mongoid::VERSION.split(".").first.to_i >= 4
@@ -3,7 +3,9 @@ class Cloudinary::Railtie < Rails::Railtie
3
3
  Dir[File.join(File.dirname(__FILE__),'../tasks/**/*.rake')].each { |f| load f }
4
4
  end
5
5
  config.after_initialize do |app|
6
- ActionView::Base.send :include, CloudinaryHelper
6
+ ActiveSupport.on_load(:action_view) do
7
+ ActionView::Base.send :include, CloudinaryHelper
8
+ end
7
9
  end
8
10
 
9
11
  ActiveSupport.on_load(:action_controller_base) do
@@ -4,7 +4,8 @@ class Cloudinary::Search
4
4
  SORT_BY = :sort_by
5
5
  AGGREGATE = :aggregate
6
6
  WITH_FIELD = :with_field
7
- KEYS_WITH_UNIQUE_VALUES = [SORT_BY, AGGREGATE, WITH_FIELD].freeze
7
+ FIELDS = :fields
8
+ KEYS_WITH_UNIQUE_VALUES = [SORT_BY, AGGREGATE, WITH_FIELD, FIELDS].freeze
8
9
 
9
10
  TTL = 300 # Used for search URLs
10
11
 
@@ -12,7 +13,8 @@ class Cloudinary::Search
12
13
  @query_hash = {
13
14
  SORT_BY => {},
14
15
  AGGREGATE => {},
15
- WITH_FIELD => {}
16
+ WITH_FIELD => {},
17
+ FIELDS => {},
16
18
  }
17
19
 
18
20
  @endpoint = self.class::ENDPOINT
@@ -59,7 +61,7 @@ class Cloudinary::Search
59
61
  #
60
62
  # @param [String] value Supported values: resource_type, type, pixels (only the image assets in the response are
61
63
  # aggregated), duration (only the video assets in the response are aggregated), format, and
62
- # bytes. For aggregation fields without discrete values, the results are divided into
64
+ # bytes. For aggregation fields without discrete values, the results are divided into
63
65
  # categories.
64
66
  # @return [Cloudinary::Search]
65
67
  def aggregate(value)
@@ -77,6 +79,19 @@ class Cloudinary::Search
77
79
  self
78
80
  end
79
81
 
82
+
83
+ # The list of the asset attributes to include for each asset in the response.
84
+ #
85
+ # @param [Array] value The array of attributes' names.
86
+ #
87
+ # @return [Cloudinary::Search]
88
+ def fields(value)
89
+ Cloudinary::Utils.build_array(value).each do |field|
90
+ @query_hash[FIELDS][field] = field
91
+ end
92
+ self
93
+ end
94
+
80
95
  # Sets the time to live of the search URL.
81
96
  #
82
97
  # @param [Object] ttl The time to live in seconds.
@@ -40,6 +40,7 @@ class Cloudinary::Uploader
40
40
  :eager_notification_url => options[:eager_notification_url],
41
41
  :exif => Cloudinary::Utils.as_safe_bool(options[:exif]),
42
42
  :eval => options[:eval],
43
+ :on_success => options[:on_success],
43
44
  :face_coordinates => Cloudinary::Utils.encode_double_array(options[:face_coordinates]),
44
45
  :faces => Cloudinary::Utils.as_safe_bool(options[:faces]),
45
46
  :folder => options[:folder],
@@ -87,16 +88,7 @@ class Cloudinary::Uploader
87
88
  def self.upload(file, options={})
88
89
  call_api("upload", options) do
89
90
  params = build_upload_params(options)
90
- if file.is_a?(Pathname)
91
- params[:file] = File.open(file, "rb")
92
- elsif file.is_a?(StringIO)
93
- file.rewind
94
- params[:file] = Cloudinary::Blob.new(file.read, options)
95
- elsif file.respond_to?(:read) || Cloudinary::Utils.is_remote?(file)
96
- params[:file] = file
97
- else
98
- params[:file] = File.open(file, "rb")
99
- end
91
+ params[:file] = Cloudinary::Utils.handle_file_param(file, options)
100
92
  [params, [:file]]
101
93
  end
102
94
  end
@@ -153,11 +145,7 @@ class Cloudinary::Uploader
153
145
  options[:resource_type] ||= :raw
154
146
  call_api("upload", options) do
155
147
  params = build_upload_params(options)
156
- if file.is_a?(Pathname) || !file.respond_to?(:read)
157
- params[:file] = File.open(file, "rb")
158
- else
159
- params[:file] = file
160
- end
148
+ params[:file] = Cloudinary::Utils.handle_file_param(file, options)
161
149
  [params, [:file]]
162
150
  end
163
151
  end
@@ -998,6 +998,12 @@ class Cloudinary::Utils
998
998
  option_value.nil? ? default_value : option_value
999
999
  end
1000
1000
 
1001
+ def self.config_option_fetch(options, option_name, default_value = nil)
1002
+ return options.fetch(option_name) if options.include?(option_name)
1003
+ option_value = Cloudinary.config.send(option_name)
1004
+ option_value.nil? ? default_value : option_value
1005
+ end
1006
+
1001
1007
  def self.as_bool(value)
1002
1008
  case value
1003
1009
  when nil then nil
@@ -1250,7 +1256,8 @@ class Cloudinary::Utils
1250
1256
  # @param options url and transformation options. This argument may be changed by the function!
1251
1257
  #
1252
1258
  def self.patch_fetch_format(options={})
1253
- if options[:type] === :fetch
1259
+ use_fetch_format = config_option_consume(options, :use_fetch_format)
1260
+ if options[:type] === :fetch || use_fetch_format
1254
1261
  format_arg = options.delete(:format)
1255
1262
  options[:fetch_format] ||= format_arg
1256
1263
  end
@@ -1295,6 +1302,27 @@ class Cloudinary::Utils
1295
1302
  }
1296
1303
  end
1297
1304
 
1305
+ # Handles file parameter.
1306
+ #
1307
+ # @param [Pathname, StringIO, File, String, int, _ToPath] file
1308
+ # @return [StringIO, File] A File object.
1309
+ #
1310
+ # @private
1311
+ def self.handle_file_param(file, options = {})
1312
+ if file.is_a?(Pathname)
1313
+ return File.open(file, "rb")
1314
+ elsif file.is_a?(Cloudinary::Blob)
1315
+ return file
1316
+ elsif file.is_a?(StringIO)
1317
+ file.rewind
1318
+ return Cloudinary::Blob.new(file.read, options)
1319
+ elsif file.respond_to?(:read) || Cloudinary::Utils.is_remote?(file)
1320
+ return file
1321
+ end
1322
+
1323
+ File.open(file, "rb")
1324
+ end
1325
+
1298
1326
  # The returned url should allow downloading the backedup asset based on the version and asset id
1299
1327
  #
1300
1328
  # asset and version id are returned with resource(<PUBLIC_ID1>, { versions: true })
@@ -1,4 +1,4 @@
1
1
  # Copyright Cloudinary
2
2
  module Cloudinary
3
- VERSION = "1.27.0"
3
+ VERSION = "1.29.0"
4
4
  end
@@ -53,7 +53,7 @@ module CloudinaryHelper
53
53
  # }
54
54
  # ])
55
55
  def cl_video_tag(source, options = {}, &block)
56
- source = strip_known_ext(source)
56
+ source = strip_known_ext(source) unless Cloudinary::Utils.config_option_fetch(options, :use_fetch_format)
57
57
  video_attributes = [:autoplay,:controls,:loop,:muted,:poster, :preload]
58
58
  options = Cloudinary::Utils.deep_symbolize_keys(DEFAULT_VIDEO_OPTIONS.merge(options))
59
59
 
@@ -155,8 +155,9 @@ module CloudinaryHelper
155
155
  content_tag('video', tag_options.merge(video_options)) do
156
156
  source_tags = sources.map do |source|
157
157
  type = source[:type]
158
+ options[:format] = type
158
159
  transformation = source[:transformations] || {}
159
- cloudinary_tag("#{source_name}.#{type}", options.merge(transformation)) do |url, _tag_options|
160
+ cloudinary_tag(source_name, options.merge(transformation)) do |url, _tag_options|
160
161
  mime_type = "video/#{(type == 'ogv' ? 'ogg' : type)}"
161
162
  if source[:codecs]
162
163
  codecs = source[:codecs].is_a?(Array) ? source[:codecs].join(", ") : source[:codecs]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudinary
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.27.0
4
+ version: 1.29.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nadav Soferman
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-07-31 00:00:00.000000000 Z
13
+ date: 2024-02-26 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: aws_cf_signer
@@ -86,16 +86,16 @@ dependencies:
86
86
  name: sqlite3
87
87
  requirement: !ruby/object:Gem::Requirement
88
88
  requirements:
89
- - - ">="
89
+ - - "<"
90
90
  - !ruby/object:Gem::Version
91
- version: '0'
91
+ version: 1.6.0
92
92
  type: :development
93
93
  prerelease: false
94
94
  version_requirements: !ruby/object:Gem::Requirement
95
95
  requirements:
96
- - - ">="
96
+ - - "<"
97
97
  - !ruby/object:Gem::Version
98
- version: '0'
98
+ version: 1.6.0
99
99
  - !ruby/object:Gem::Dependency
100
100
  name: rspec
101
101
  requirement: !ruby/object:Gem::Requirement