cloudinary 1.8.1 → 1.8.2

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
  SHA1:
3
- metadata.gz: 07e321996ca2cae3a8eec12d27de1aed453853e7
4
- data.tar.gz: 579c2b752735619c42ae516c9cbec268136ddbbe
3
+ metadata.gz: 8dee4c14d8ddf334a1ff60a96cc7bcb85ef82b25
4
+ data.tar.gz: 644319b8bdf30ba48b3ab57facc45364aedb3a3d
5
5
  SHA512:
6
- metadata.gz: 4f0bdc46e84bf87fb80a1ea3a3934088b2079d910f4dfcdbe192f1318c760d386b639d66d902d5ccdfedba3a90827483c96c0c7ff6cc2ad50fd594e389b2b8e8
7
- data.tar.gz: 1b80560e163319804899b0aa6fb378fcdedc260ae087977938a3de172d88b0ffff762dfa0b8b9688a9cbfde2facfe956ce1b67e6eada52d874ababd16ceb5176
6
+ metadata.gz: 3af0f955aa2c7a8eeb9f66c2fc92fdc04be4cfeb4a0bc9f6fc203d07ba096e2eaa850d8ca750f402c798b47326c180623e42ddc5d59b258e284ba25a7edef4ff
7
+ data.tar.gz: f583837bfc36ac1e0db6dd5b5335600fbac2fa7c20cb9a28c0b0578c989e094fb3bacebc22509e9f30944bc0065fcf478e649f4ffbb3f34011b246a3efd1e844
data/.travis.yml CHANGED
@@ -1,3 +1,8 @@
1
+ language: ruby
2
+
3
+ before_install:
4
+ - gem install bundler
5
+
1
6
  rvm:
2
7
  - 1.9.3
3
8
  - 2.2.3
data/CHANGELOG.md CHANGED
@@ -1,4 +1,16 @@
1
1
 
2
+ 1.8.2 / 2017-11-22
3
+ ==================
4
+
5
+ * Fix URL signature
6
+ * Use the correct method for updating a column
7
+ * Add support for `named` parameter in list transformation API
8
+ * load environment when running sync_static task
9
+ * Fix the overwritten initializer for hash (#273)
10
+ * Force TravisCI to install bundler
11
+ * Fix CloudinaryFile::exists? method. Solves #193 #205
12
+ * Update Readme to point to HTTPS URLs of cloudinary.com
13
+
2
14
  1.8.1 / 2017-05-16
3
15
  ==================
4
16
 
data/README.md CHANGED
@@ -13,7 +13,7 @@ Cloudinary provides URL and HTTP based APIs that can be easily integrated with a
13
13
  For Ruby on Rails, Cloudinary provides a GEM for simplifying the integration even further.
14
14
 
15
15
  ## Getting started guide
16
- ![More](http://res.cloudinary.com/cloudinary/image/upload/see_more_bullet.png) **Take a look at our [Getting started guide of Ruby on Rails](http://cloudinary.com/documentation/rails_integration#getting_started_guide)**.
16
+ ![More](http://res.cloudinary.com/cloudinary/image/upload/see_more_bullet.png) **Take a look at our [Getting started guide of Ruby on Rails](https://cloudinary.com/documentation/rails_integration#getting_started_guide)**.
17
17
 
18
18
  ## Setup ######################################################################
19
19
 
@@ -68,7 +68,7 @@ Converting to a 150x100 PNG with rounded corners of 20 pixels:
68
68
 
69
69
  ![Sample 150x150 Rounded PNG](https://res.cloudinary.com/demo/image/upload/w_150,h_100,c_fill,r_20/sample.png "Sample 150x150 Rounded PNG")
70
70
 
71
- For plenty more transformation options, see our [image transformations documentation](http://cloudinary.com/documentation/image_transformations).
71
+ For plenty more transformation options, see our [image transformations documentation](https://cloudinary.com/documentation/image_transformations).
72
72
 
73
73
  Generating a 120x90 thumbnail based on automatic face detection of the Facebook profile picture of Bill Clinton:
74
74
 
@@ -76,7 +76,7 @@ Generating a 120x90 thumbnail based on automatic face detection of the Facebook
76
76
 
77
77
  ![Facebook 90x120](https://res.cloudinary.com/demo/image/facebook/c_thumb,g_face,h_90,w_120/billclinton.jpg "Facebook 90x200")
78
78
 
79
- For more details, see our documentation for embedding [Facebook](http://cloudinary.com/documentation/facebook_profile_pictures) and [Twitter](http://cloudinary.com/documentation/twitter_profile_pictures) profile pictures.
79
+ For more details, see our documentation for embedding [Facebook](https://cloudinary.com/documentation/facebook_profile_pictures) and [Twitter](https://cloudinary.com/documentation/twitter_profile_pictures) profile pictures.
80
80
 
81
81
 
82
82
  ## Usage
@@ -84,7 +84,7 @@ For more details, see our documentation for embedding [Facebook](http://cloudina
84
84
  ### Configuration
85
85
 
86
86
  Each request for building a URL of a remote cloud resource must have the `cloud_name` parameter set.
87
- Each request to our secure APIs (e.g., image uploads, eager sprite generation) must have the `api_key` and `api_secret` parameters set. See [API, URLs and access identifiers](http://cloudinary.com/documentation/api_and_access_identifiers) for more details.
87
+ Each request to our secure APIs (e.g., image uploads, eager sprite generation) must have the `api_key` and `api_secret` parameters set. See [API, URLs and access identifiers](https://cloudinary.com/documentation/api_and_access_identifiers) for more details.
88
88
 
89
89
  Setting the `cloud_name`, `api_key` and `api_secret` parameters can be done either directly in each call to a Cloudinary method or by globally setting using a YAML configuration file.
90
90
 
@@ -130,7 +130,7 @@ Same goes for Twitter:
130
130
 
131
131
  twitter_name_profile_image_tag("billclinton.jpg")
132
132
 
133
- ![More](http://res.cloudinary.com/cloudinary/image/upload/see_more_bullet.png) **See [our documentation](http://cloudinary.com/documentation/rails_image_manipulation) for more information about displaying and transforming images in Rails**.
133
+ ![More](http://res.cloudinary.com/cloudinary/image/upload/see_more_bullet.png) **See [our documentation](https://cloudinary.com/documentation/rails_image_manipulation) for more information about displaying and transforming images in Rails**.
134
134
 
135
135
 
136
136
 
@@ -157,7 +157,7 @@ You can also specify your own public ID:
157
157
  http://res.cloudinary.com/demo/image/upload/sample_remote.jpg
158
158
 
159
159
 
160
- ![More](http://res.cloudinary.com/cloudinary/image/upload/see_more_bullet.png) **See [our documentation](http://cloudinary.com/documentation/rails_image_upload) for plenty more options of uploading to the cloud from your Ruby code or directly from the browser**.
160
+ ![More](http://res.cloudinary.com/cloudinary/image/upload/see_more_bullet.png) **See [our documentation](https://cloudinary.com/documentation/rails_image_upload) for plenty more options of uploading to the cloud from your Ruby code or directly from the browser**.
161
161
 
162
162
 
163
163
  ### CarrierWave Integration
@@ -172,9 +172,9 @@ Cloudinary's Ruby GEM includes an optional plugin for [CarrierWave](https://gith
172
172
  ...
173
173
  end
174
174
 
175
- ![More](http://res.cloudinary.com/cloudinary/image/upload/see_more_bullet.png) **For more details on CarrierWave integration see [our documentation](http://cloudinary.com/documentation/rails_carrierwave)**.
175
+ ![More](http://res.cloudinary.com/cloudinary/image/upload/see_more_bullet.png) **For more details on CarrierWave integration see [our documentation](https://cloudinary.com/documentation/rails_carrierwave)**.
176
176
 
177
- We also published an interesting blog post about [Ruby on Rails image uploads with CarrierWave and Cloudinary](http://cloudinary.com/blog/ruby_on_rails_image_uploads_with_carrierwave_and_cloudinary).
177
+ We also published an interesting blog post about [Ruby on Rails image uploads with CarrierWave and Cloudinary](https://cloudinary.com/blog/ruby_on_rails_image_uploads_with_carrierwave_and_cloudinary).
178
178
 
179
179
  #### Neo4j integration
180
180
 
@@ -205,7 +205,7 @@ To automatically set-up Cloudinary's configuration, include the following line i
205
205
 
206
206
  #### Uploading images from the browser
207
207
 
208
- The Cloudinary JavaScript library utilizes the Blueimp File Upload library to support image uploading from the browser. See the [documentation](http://cloudinary.com/documentation/jquery_image_upload) for more details.
208
+ The Cloudinary JavaScript library utilizes the Blueimp File Upload library to support image uploading from the browser. See the [documentation](https://cloudinary.com/documentation/jquery_image_upload) for more details.
209
209
 
210
210
  |Important|
211
211
  |---------|
@@ -233,21 +233,22 @@ Please consult with the [README file](https://github.com/cloudinary/cloudinary_g
233
233
 
234
234
  Additional resources are available at:
235
235
 
236
- * [Website](http://cloudinary.com)
237
- * [Documentation](http://cloudinary.com/documentation)
238
- * [Knowledge Base](http://support.cloudinary.com/forums)
239
- * [Documentation for Ruby on Rails integration](http://cloudinary.com/documentation/rails_integration)
240
- * [Ruby on Rails image upload documentation](http://cloudinary.com/documentation/rails_image_upload)
241
- * [Ruby on Rails image manipulation documentation](http://cloudinary.com/documentation/rails_image_manipulation)
242
- * [Image transformations documentation](http://cloudinary.com/documentation/image_transformations)
236
+ * [Website](https://cloudinary.com)
237
+ * [Interactive demo](https://demo.cloudinary.com/default)
238
+ * [Documentation](https://cloudinary.com/documentation)
239
+ * [Knowledge Base](https://support.cloudinary.com/hc/en-us)
240
+ * [Documentation for Ruby on Rails integration](https://cloudinary.com/documentation/rails_integration)
241
+ * [Ruby on Rails image upload documentation](https://cloudinary.com/documentation/rails_image_upload)
242
+ * [Ruby on Rails image manipulation documentation](https://cloudinary.com/documentation/rails_image_manipulation)
243
+ * [Image transformations documentation](https://cloudinary.com/documentation/image_transformations)
243
244
 
244
245
  ## Support
245
246
 
246
247
  You can [open an issue through GitHub](https://github.com/cloudinary/cloudinary_gem/issues).
247
248
 
248
- Contact us [http://cloudinary.com/contact](http://cloudinary.com/contact)
249
+ Contact us [https://cloudinary.com/contact](https://cloudinary.com/contact)
249
250
 
250
- Stay tuned for updates, tips and tutorials: [Blog](http://cloudinary.com/blog), [Twitter](https://twitter.com/cloudinary), [Facebook](http://www.facebook.com/Cloudinary).
251
+ Stay tuned for updates, tips and tutorials: [Blog](https://cloudinary.com/blog), [Twitter](https://twitter.com/cloudinary), [Facebook](https://www.facebook.com/Cloudinary).
251
252
 
252
253
 
253
254
  ## License #######################################################################
@@ -10,14 +10,19 @@ class Cloudinary::Api
10
10
  class BadRequest < Error; end
11
11
  class GeneralError < Error; end
12
12
  class AuthorizationRequired < Error; end
13
+
13
14
  class Response < Hash
14
15
  attr_reader :rate_limit_reset_at, :rate_limit_remaining, :rate_limit_allowed
15
16
 
16
- def initialize(response)
17
- self.update(Cloudinary::Api.send(:parse_json_response, response))
18
- @rate_limit_allowed = response.headers[:x_featureratelimit_limit].to_i
19
- @rate_limit_reset_at = Time.parse(response.headers[:x_featureratelimit_reset])
20
- @rate_limit_remaining = response.headers[:x_featureratelimit_remaining].to_i
17
+ 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
21
+
22
+ @rate_limit_allowed = response.headers[:x_featureratelimit_limit].to_i
23
+ @rate_limit_reset_at = Time.parse(response.headers[:x_featureratelimit_reset])
24
+ @rate_limit_remaining = response.headers[:x_featureratelimit_remaining].to_i
25
+ end
21
26
  end
22
27
  end
23
28
 
@@ -160,7 +165,7 @@ class Cloudinary::Api
160
165
  end
161
166
 
162
167
  def self.transformations(options={})
163
- call_api(:get, "transformations", only(options, :next_cursor, :max_results), options)
168
+ call_api(:get, "transformations", only(options, :named, :next_cursor, :max_results), options)
164
169
  end
165
170
 
166
171
  def self.transformation(transformation, options={})
@@ -176,7 +176,8 @@ module Cloudinary::CarrierWave
176
176
  end
177
177
 
178
178
  def exists?
179
- Cloudinary::Uploader.exists?(self.identifier, :type=>self.storage_type, :resource_type=>self.resource_type)
179
+ public_id = @resource_type == "raw" ? self.filename : self.public_id
180
+ Cloudinary::Uploader.exists?(public_id, :version=>self.version, :type=>self.storage_type, :resource_type=>self.resource_type)
180
181
  end
181
182
 
182
183
  def read(options={})
@@ -89,7 +89,7 @@ class Cloudinary::CarrierWave::Storage < ::CarrierWave::Storage::Abstract
89
89
  uploader.model.set(column, name)
90
90
  end
91
91
  elsif defined?(Neo4j::VERSION) && Neo4j::VERSION.split(".").first.to_i >= 5
92
- uploader.model.set(column, name)
92
+ uploader.model.write_attribute(column, name)
93
93
  elsif defined?(Sequel::Model) && uploader.model.is_a?(Sequel::Model)
94
94
  # Sequel support
95
95
  uploader.model.this.update(column => name)
@@ -397,11 +397,7 @@ class Cloudinary::Utils
397
397
  transformation = transformation.gsub(%r(([^:])//), '\1/')
398
398
  if sign_url && ( !auth_token || auth_token.empty?)
399
399
  to_sign = [transformation, sign_version && version, source_to_sign].reject(&:blank?).join("/")
400
- i = 0
401
- while to_sign != CGI.unescape(to_sign) && i <10
402
- to_sign = CGI.unescape(to_sign)
403
- i = i + 1
404
- end
400
+ to_sign = fully_unescape(to_sign)
405
401
  signature = 's--' + Base64.urlsafe_encode64(Digest::SHA1.digest(to_sign + secret))[0,8] + '--'
406
402
  end
407
403
 
@@ -848,8 +844,24 @@ class Cloudinary::Utils
848
844
  Cloudinary::AuthToken.generate options
849
845
 
850
846
  end
847
+
851
848
  private
852
849
 
850
+
851
+ # Repeatedly unescapes the source until no more unescaping is possible or 10 cycles elapsed
852
+ # @param [String] source - a (possibly) escaped string
853
+ # @return [String] the fully unescaped string
854
+ # @private
855
+ def self.fully_unescape(source)
856
+ i = 0
857
+ while source != CGI.unescape(source) && i <10
858
+ source = CGI.unescape(source.gsub('+', '%2B')) # don't let unescape replace '+' with space
859
+ i = i + 1
860
+ end
861
+ source
862
+ end
863
+ private_class_method :fully_unescape
864
+
853
865
  def self.hash_query_params(hash)
854
866
  if hash.respond_to?("to_query")
855
867
  hash.to_query
@@ -1,4 +1,4 @@
1
1
  # Copyright Cloudinary
2
2
  module Cloudinary
3
- VERSION = "1.8.1"
3
+ VERSION = "1.8.2"
4
4
  end
@@ -1,9 +1,9 @@
1
1
  unless Rake::Task.task_defined?('cloudinary:sync_static') # prevent double-loading/execution
2
2
  namespace :cloudinary do
3
3
  desc "Sync static resources with cloudinary"
4
- task :sync_static do
4
+ task :sync_static => :environment do
5
5
  delete_missing = ENV['DELETE_MISSING'] == 'true' || ENV['DELETE_MISSING'] == '1'
6
6
  Cloudinary::Static.sync(:delete_missing => delete_missing)
7
7
  end
8
8
  end
9
- end
9
+ end
data/spec/api_spec.rb CHANGED
@@ -78,7 +78,7 @@ describe Cloudinary::Api do
78
78
  expect(resources.map{|resource| resource["tags"]}.flatten).to include(TEST_TAG, TIMESTAMP_TAG)
79
79
  expect(resources.map{|resource| resource["context"]}).to include({"custom" => {"key" => "value"}})
80
80
  end
81
-
81
+
82
82
  it "should allow listing resources by context" do
83
83
  resources = @api.resources_by_context(test_key)["resources"]
84
84
  expect(resources.count).to eq(2)
@@ -94,7 +94,7 @@ describe Cloudinary::Api do
94
94
  expect(resources.map{|resource| resource["tags"]}.flatten).to include(TEST_TAG, TIMESTAMP_TAG)
95
95
  expect(resources.map{|resource| resource["context"]}).to include({"custom" => {"key" => "value"}})
96
96
  end
97
-
97
+
98
98
  it "should allow listing resources by start date", :start_at => true do
99
99
  start_at = Time.now
100
100
  expect(RestClient::Request).to receive(:execute).with(deep_hash_value( {[:payload, :start_at] => start_at, [:payload, :direction] => "asc"}))
@@ -129,7 +129,7 @@ describe Cloudinary::Api do
129
129
  expect(resource["bytes"]).to eq(3381)
130
130
  expect(resource["derived"].length).to eq(1)
131
131
  end
132
-
132
+
133
133
  it "should allow deleting derived resource" do
134
134
  derived_resource_id = "derived_id"
135
135
  expect(RestClient::Request).to receive(:execute).with(deep_hash_value( {[:payload, :derived_resource_ids] => derived_resource_id}))
@@ -199,7 +199,7 @@ describe Cloudinary::Api do
199
199
  tags = @api.tags(:prefix=>"api_test_no_such_tag")["tags"]
200
200
  expect(tags).to be_blank
201
201
  end
202
-
202
+
203
203
  describe 'transformations' do
204
204
  it "should allow listing transformations" do
205
205
  transformation = @api.transformations(max_results: 500)["transformations"].find { |transformation| transformation["name"] == TEST_TRANSFOMATION }
@@ -265,6 +265,11 @@ describe Cloudinary::Api do
265
265
  @api.update_transformation(public_id, :unsafe_update => { "crop" => "scale", "width" => 103 })
266
266
  end
267
267
 
268
+ it "should allow listing of named transformations" do
269
+ expect(RestClient::Request).to receive(:execute).with(deep_hash_value( [:payload, :named ]=> true))
270
+ @api.transformations :named => true
271
+ end
272
+
268
273
  end
269
274
  it "should allow deleting implicit transformation" do
270
275
  @api.transformation(TEST_TRANSFOMATION)
@@ -272,7 +277,7 @@ describe Cloudinary::Api do
272
277
  expect { @api.transformation(TEST_TRANSFOMATION) }.to raise_error(Cloudinary::Api::NotFound)
273
278
  end
274
279
  end
275
-
280
+
276
281
  it "should allow creating upload_presets" do
277
282
  expected = {:url => /.*\/upload_presets$/,
278
283
  [:payload, :name] => "new_preset",
@@ -305,7 +310,7 @@ describe Cloudinary::Api do
305
310
  expect(preset["settings"]["context"]).to eq({"a" => "b", "c" => "d"})
306
311
  expect(preset["settings"]["tags"]).to eq(["a","b","c", TEST_TAG, TIMESTAMP_TAG])
307
312
  end
308
-
313
+
309
314
  it "should allow deleting upload_presets", :upload_preset => true do
310
315
  id = "#{prefix}_upload_preset"
311
316
  @api.create_upload_preset(:name => id, :folder => "folder", :tags => [TEST_TAG, TIMESTAMP_TAG])
@@ -313,7 +318,7 @@ describe Cloudinary::Api do
313
318
  @api.delete_upload_preset(id)
314
319
  expect{preset = @api.upload_preset(id)}.to raise_error(Cloudinary::Api::NotFound)
315
320
  end
316
-
321
+
317
322
  it "should allow updating upload_presets", :upload_preset => true do
318
323
  name = @api.create_upload_preset(:folder => "folder", :tags => [TEST_TAG, TIMESTAMP_TAG])["name"]
319
324
  preset = @api.upload_preset(name)
@@ -323,7 +328,7 @@ describe Cloudinary::Api do
323
328
  expect(preset["unsigned"]).to eq(true)
324
329
  expect(preset["settings"]).to eq({"folder" => "folder", "colors" => true, "disallow_public_id" => true, "tags" => [TEST_TAG, TIMESTAMP_TAG]})
325
330
  end
326
-
331
+
327
332
  # this test must be last because it deletes (potentially) all dependent transformations which some tests rely on. Excluded by default.
328
333
  skip "should allow deleting all resources", :delete_all=>true do
329
334
  Cloudinary::Uploader.upload(TEST_IMG, :public_id=>"api_test5", :eager=>[:width=>101,:crop=>:scale], :tags => [TEST_TAG, TIMESTAMP_TAG])
@@ -335,7 +340,7 @@ describe Cloudinary::Api do
335
340
  expect(resource).not_to be_blank
336
341
  expect(resource["derived"].length).to eq(0)
337
342
  end
338
-
343
+
339
344
  it "should support setting manual moderation status" do
340
345
  result = Cloudinary::Uploader.upload(TEST_IMG, {:moderation => :manual, :tags => [TEST_TAG, TIMESTAMP_TAG]})
341
346
  expect(result["moderation"][0]["status"]).to eq("pending")
@@ -344,17 +349,17 @@ describe Cloudinary::Api do
344
349
  expect(api_result["moderation"][0]["status"]).to eq("approved")
345
350
  expect(api_result["moderation"][0]["kind"]).to eq("manual")
346
351
  end
347
-
352
+
348
353
  it "should support requesting raw conversion" do
349
354
  result = Cloudinary::Uploader.upload("spec/docx.docx", :resource_type => :raw, :tags => [TEST_TAG, TIMESTAMP_TAG])
350
355
  expect{Cloudinary::Api.update(result["public_id"], {:resource_type => :raw, :raw_convert => :illegal})}.to raise_error(Cloudinary::Api::BadRequest, /^Illegal value|not a valid/)
351
356
  end
352
-
357
+
353
358
  it "should support requesting categorization" do
354
359
  result = Cloudinary::Uploader.upload(TEST_IMG, :tags => [TEST_TAG, TIMESTAMP_TAG])
355
360
  expect{Cloudinary::Api.update(result["public_id"], {:categorization => :illegal})}.to raise_error(Cloudinary::Api::BadRequest, /^Illegal value/)
356
361
  end
357
-
362
+
358
363
  it "should support requesting detection with server notification", :focus => true do
359
364
  expected = {
360
365
  [:payload, :detection] => "adv_face",
@@ -363,12 +368,12 @@ describe Cloudinary::Api do
363
368
  expect(RestClient::Request).to receive(:execute).with(deep_hash_value(expected))
364
369
  Cloudinary::Api.update("public_id", {:detection => "adv_face", :notification_url => "http://example.com"})
365
370
  end
366
-
371
+
367
372
  it "should support requesting auto_tagging" do
368
373
  expect(RestClient::Request).to receive(:execute).with(deep_hash_value( [:payload, :auto_tagging] => 0.5))
369
374
  Cloudinary::Api.update("public_id", {:auto_tagging => 0.5})
370
375
  end
371
-
376
+
372
377
  it "should support listing by moderation kind and value" do
373
378
  expect(RestClient::Request).to receive(:execute).with(deep_hash_value([:url] => /.*manual\/approved$/, [:payload, :max_results] => 1000))
374
379
  Cloudinary::Api.resources_by_moderation(:manual, :approved, :max_results => 1000)
@@ -462,12 +467,12 @@ describe Cloudinary::Api do
462
467
 
463
468
  expect(result["published"]).to be_an_instance_of(Array)
464
469
  expect(result["published"].length).to eq(1)
465
-
470
+
466
471
  resource = result["published"][0]
467
-
472
+
468
473
  expect(resource["public_id"]).to eq(publicId)
469
474
  expect(resource["type"]).to eq('upload')
470
-
475
+
471
476
  bytes = resource["bytes"]
472
477
  end
473
478
  it "should publish resources by prefix and overwrite" do
@@ -475,13 +480,13 @@ describe Cloudinary::Api do
475
480
 
476
481
  expect(result["published"]).to be_an_instance_of(Array)
477
482
  expect(result["published"].length).to eq(1)
478
-
483
+
479
484
  resource = result["published"][0]
480
-
485
+
481
486
  expect(resource["public_id"]).to eq(publicId)
482
487
  expect(resource["bytes"]).not_to eq(bytes)
483
488
  expect(resource["type"]).to eq('upload')
484
-
489
+
485
490
  bytes = resource["bytes"]
486
491
  end
487
492
  it "should publish resources by tag and overwrite" do
@@ -489,15 +494,52 @@ describe Cloudinary::Api do
489
494
 
490
495
  expect(result["published"]).to be_an_instance_of(Array)
491
496
  expect(result["published"].length).to eq(1)
492
-
497
+
493
498
  resource = result["published"][0]
494
-
499
+
495
500
  expect(resource["public_id"]).to eq(publicId)
496
501
  expect(resource["bytes"]).not_to eq(bytes)
497
502
  expect(resource["type"]).to eq('upload')
498
-
503
+
499
504
  bytes = resource["bytes"]
500
505
  end
506
+ end
507
+ end
508
+
509
+ describe Cloudinary::Api::Response do
510
+ let(:api_response) { described_class.new }
511
+
512
+ shared_examples 'a Hash' do
513
+ it 'inherits from Hash' do
514
+ expect(api_response).to be_a Hash
515
+ end
516
+ end
517
+
518
+ context 'when there is no argument given on instantiation' do
519
+ it 'does not raise an error' do
520
+ expect { api_response }.to_not raise_error
521
+ end
522
+
523
+ it_behaves_like 'a Hash'
524
+ end
525
+
526
+ context 'when the response is nil' do
527
+ it 'does not raise an error' do
528
+ expect { described_class.new nil }.to_not raise_error
529
+ end
530
+
531
+ it_behaves_like 'a Hash'
532
+ end
533
+
534
+ context 'when the response is present' do
535
+ let(:body) { { 'foo' => 'bar' } }
536
+ let(:http_response) { double code: 200, body: body.to_json, headers: { x_featureratelimit_reset: Time.new.to_s } }
537
+ let(:api_response) { described_class.new http_response }
538
+
539
+ it 'sets the instantiated self as the parsed response which is a Hash' do
540
+ expect(api_response).to eq body
541
+ end
501
542
 
543
+ it_behaves_like 'a Hash'
502
544
  end
503
545
  end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ require 'cloudinary'
3
+
4
+ module CarrierWave
5
+ module Storage
6
+ class Abstract
7
+ def initialize(uploader)
8
+ @uploader = uploader
9
+ end
10
+
11
+ attr_accessor :uploader
12
+ end
13
+ end
14
+ class SanitizedFile; end
15
+ end
16
+
17
+ RSpec.describe Cloudinary::CarrierWave::Storage do
18
+ describe '#store_cloudinary_identifier' do
19
+ let(:column) { 'example_field' }
20
+ let(:model) { double :model, _mounter: mount, write_attribute: true }
21
+ let(:mount) { double :mount, serialization_column: column }
22
+ let(:storage) { Cloudinary::CarrierWave::Storage.new(uploader) }
23
+ let(:store_identifier) { storage.store_cloudinary_identifier('1', 'test.png') }
24
+ let(:uploader) { double :uploader, model: model, mounted_as: :example, use_extended_identifier?: false }
25
+
26
+ describe 'when the ORM is Neo4j 5 and above' do
27
+ before { stub_const('Neo4j::VERSION', '5.0') }
28
+
29
+ subject! { store_identifier }
30
+
31
+ it 'writes the name to the datastore without triggering validations' do
32
+ expect(model).to have_received(:write_attribute).with(column, 'v1/test.png')
33
+ end
34
+ end
35
+
36
+ describe 'when the ORM is Neo4j 4' do
37
+ before { stub_const('Neo4j::VERSION', '4.0') }
38
+
39
+ it 'raises an unsupported exception' do
40
+ expect { store_identifier }.to raise_error(CloudinaryException)
41
+ end
42
+ end
43
+ end
44
+ end
data/spec/utils_spec.rb CHANGED
@@ -120,6 +120,17 @@ describe Cloudinary::Utils do
120
120
  .and empty_options
121
121
  end
122
122
 
123
+ it "should sign a url" do
124
+ expected = Cloudinary::Utils.cloudinary_url "some_public_id.jpg",
125
+ :cloud_name => "test",
126
+ :api_key => "123456789012345",
127
+ :api_secret => "AbcdEfghIjklmnopq1234567890",
128
+ :type => "authenticated",
129
+ :sign_url => true,
130
+ :overlay => "text:Helvetica_50:test+text"
131
+ expect(expected).to eq("http://res.cloudinary.com/test/image/authenticated/s--j5Z1ILxd--/l_text:Helvetica_50:test+text/some_public_id.jpg")
132
+ end
133
+
123
134
  it "should not sign the url_suffix" do
124
135
  expected_signture = Cloudinary::Utils.cloudinary_url("test", :format => "jpg", :sign_url => true).match(/s--[0-9A-Za-z_-]{8}--/).to_s
125
136
  expect(["test", { :url_suffix => "hello", :private_cdn => true, :format => "jpg", :sign_url => true }])
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.8.1
4
+ version: 1.8.2
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: 2017-05-16 00:00:00.000000000 Z
13
+ date: 2017-11-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: aws_cf_signer
@@ -184,6 +184,7 @@ files:
184
184
  - spec/sample_asset_file.tsv
185
185
  - spec/search_spec.rb
186
186
  - spec/spec_helper.rb
187
+ - spec/storage_spec.rb
187
188
  - spec/streaminig_profiles_api_spec.rb
188
189
  - spec/support/helpers/temp_file_helpers.rb
189
190
  - spec/support/shared_contexts/rake.rb
@@ -224,7 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
224
225
  version: '0'
225
226
  requirements: []
226
227
  rubyforge_project: cloudinary
227
- rubygems_version: 2.6.10
228
+ rubygems_version: 2.6.12
228
229
  signing_key:
229
230
  specification_version: 4
230
231
  summary: Client library for easily using the Cloudinary service
@@ -244,6 +245,7 @@ test_files:
244
245
  - spec/sample_asset_file.tsv
245
246
  - spec/search_spec.rb
246
247
  - spec/spec_helper.rb
248
+ - spec/storage_spec.rb
247
249
  - spec/streaminig_profiles_api_spec.rb
248
250
  - spec/support/helpers/temp_file_helpers.rb
249
251
  - spec/support/shared_contexts/rake.rb