cloudinary 1.8.1 → 1.8.2

Sign up to get free protection for your applications and to get access to all the features.
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