cloudinary 1.0.68 → 1.0.69

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,12 @@
1
+ = Version 1.0.69 - 2014-02-25
2
+ * Admin API update method.
3
+ * Admin API listing by moderation kind and status.
4
+ * Support moderation status in admin API listing.
5
+ * Support moderation flag in upload.
6
+ * New upload and update API parameters: moderation, ocr, raw_conversion, categorization, detection, similarity_search and auto_tagging.
7
+ * Allow CloudinaryHelper to be included into standalone classes.
8
+ * Added support for Sequel models using CarrierWave.
9
+
1
10
  = Version 1.0.68 - 2014-02-16
2
11
  * Support for uploading large raw files.
3
12
  * Correct support for image_tag and image_path override.
@@ -36,20 +36,26 @@ class Cloudinary::Api
36
36
  type = options[:type]
37
37
  uri = "resources/#{resource_type}"
38
38
  uri += "/#{type}" if !type.blank?
39
- call_api(:get, uri, only(options, :next_cursor, :max_results, :prefix, :tags, :context, :direction), options)
39
+ call_api(:get, uri, only(options, :next_cursor, :max_results, :prefix, :tags, :context, :moderations, :direction), options)
40
40
  end
41
41
 
42
42
  def self.resources_by_tag(tag, options={})
43
43
  resource_type = options[:resource_type] || "image"
44
44
  uri = "resources/#{resource_type}/tags/#{tag}"
45
- call_api(:get, uri, only(options, :next_cursor, :max_results, :tags, :context, :direction), options)
45
+ call_api(:get, uri, only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction), options)
46
+ end
47
+
48
+ def self.resources_by_moderation(kind, status, options={})
49
+ resource_type = options[:resource_type] || "image"
50
+ uri = "resources/#{resource_type}/moderations/#{kind}/#{status}"
51
+ call_api(:get, uri, only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction), options)
46
52
  end
47
53
 
48
54
  def self.resources_by_ids(public_ids, options={})
49
55
  resource_type = options[:resource_type] || "image"
50
56
  type = options[:type] || "upload"
51
57
  uri = "resources/#{resource_type}/#{type}"
52
- call_api(:get, uri, only(options, :tags, :context).merge(:public_ids => public_ids), options)
58
+ call_api(:get, uri, only(options, :tags, :context, :moderations).merge(:public_ids => public_ids), options)
53
59
  end
54
60
 
55
61
  def self.resource(public_id, options={})
@@ -59,6 +65,25 @@ class Cloudinary::Api
59
65
  call_api(:get, uri, only(options, :colors, :exif, :faces, :image_metadata, :pages, :max_results), options)
60
66
  end
61
67
 
68
+ def self.update(public_id, options={})
69
+ resource_type = options[:resource_type] || "image"
70
+ type = options[:type] || "upload"
71
+ uri = "resources/#{resource_type}/#{type}/#{public_id}"
72
+ update_options = {
73
+ :tags => options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(","),
74
+ :context => Cloudinary::Utils.encode_hash(options[:context]),
75
+ :face_coordinates => Cloudinary::Utils.encode_double_array(options[:face_coordinates]),
76
+ :moderation_status => options[:moderation_status],
77
+ :raw_convert => options[:raw_convert],
78
+ :ocr => options[:ocr],
79
+ :categorization => options[:categorization],
80
+ :detection => options[:detection],
81
+ :similarity_search => options[:similarity_search],
82
+ :auto_tagging => options[:auto_tagging] && options[:auto_tagging].to_f
83
+ }
84
+ call_api(:post, uri, update_options, options)
85
+ end
86
+
62
87
  def self.delete_resources(public_ids, options={})
63
88
  resource_type = options[:resource_type] || "image"
64
89
  type = options[:type] || "upload"
@@ -64,6 +64,11 @@ class Cloudinary::CarrierWave::Storage < ::CarrierWave::Storage::Abstract
64
64
  store_cloudinary_identifier(version, filename)
65
65
  end
66
66
 
67
+ # Updates the model mounter identifier with version information.
68
+ #
69
+ # Carrierwave uses hooks when integrating with ORMs so it's important to
70
+ # update the identifier in a way that does not trigger hooks again or else
71
+ # you'll get stuck in a loop.
67
72
  def store_cloudinary_identifier(version, filename)
68
73
  name = "v#{version}/#{filename}"
69
74
  model_class = uploader.model.class
@@ -83,11 +88,14 @@ class Cloudinary::CarrierWave::Storage < ::CarrierWave::Storage::Abstract
83
88
  else
84
89
  uploader.model.set(column, name)
85
90
  end
91
+ elsif defined?(Sequel::Model) && uploader.model.is_a?(Sequel::Model)
92
+ # Sequel support
93
+ uploader.model.this.update(column => name)
86
94
  elsif model_class.respond_to?(:update_all) && uploader.model.respond_to?(:_id)
87
95
  model_class.where(:_id=>uploader.model._id).update_all(column=>name)
88
96
  uploader.model.send :write_attribute, column, name
89
97
  else
90
- raise CloudinaryException, "Only ActiveRecord and Mongoid are supported at the moment!"
98
+ raise CloudinaryException, "Only ActiveRecord, Mongoid and Sequel are supported at the moment!"
91
99
  end
92
100
  end
93
101
  end
@@ -195,6 +195,9 @@ module CloudinaryHelper
195
195
  def self.included(base)
196
196
  ActionView::Helpers::FormBuilder.send(:include, Cloudinary::FormBuilder)
197
197
  base.class_eval do
198
+ if !method_defined?(:image_tag)
199
+ include ActionView::Helpers::AssetTagHelper
200
+ end
198
201
  if defined?(Rails) && !Rails.version.start_with?("2") && Cloudinary.config.enhance_image_tag
199
202
  alias_method_chain :image_tag, :cloudinary
200
203
  alias_method_chain :image_path, :cloudinary
@@ -38,10 +38,17 @@ class Cloudinary::Uploader
38
38
  :eager_async=>Cloudinary::Utils.as_safe_bool(options[:eager_async]),
39
39
  :proxy=>options[:proxy],
40
40
  :folder=>options[:folder],
41
+ :allowed_formats => Cloudinary::Utils.build_array(options[:allowed_formats]).join(","),
41
42
  :tags=>options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(","),
42
- :allowed_formats => Cloudinary::Utils.build_array(options[:allowed_formats]).join(","),
43
43
  :context => Cloudinary::Utils.encode_hash(options[:context]),
44
- :face_coordinates => Cloudinary::Utils.encode_double_array(options[:face_coordinates])}
44
+ :face_coordinates => Cloudinary::Utils.encode_double_array(options[:face_coordinates]),
45
+ :moderation => options[:moderation],
46
+ :raw_convert => options[:raw_convert],
47
+ :ocr => options[:ocr],
48
+ :categorization => options[:categorization],
49
+ :detection => options[:detection],
50
+ :similarity_search => options[:similarity_search],
51
+ :auto_tagging => options[:auto_tagging] && options[:auto_tagging].to_f}
45
52
  params
46
53
  end
47
54
 
@@ -59,44 +66,44 @@ class Cloudinary::Uploader
59
66
  end
60
67
  end
61
68
 
62
- # Upload large raw files. Note that public_id should include an extension for best results.
63
- def self.upload_large(file, public_id, options={})
64
- if file.is_a?(Pathname) || !file.respond_to?(:read)
65
- file = File.open(file, "rb")
66
- end
67
- upload = upload_id = nil
68
- index = 1
69
- while !file.eof?
70
- buffer = file.read(20_000_000)
71
- upload = upload_large_part(Cloudinary::Blob.new(buffer), public_id, options.merge(:upload_id=>upload_id, :part_number=>index, :final=>file.eof?))
72
- upload_id = upload["upload_id"]
73
- index += 1
74
- end
75
- upload
76
- end
77
-
78
-
79
- # Upload large raw files. Note that public_id should include an extension for best results.
80
- def self.upload_large_part(file, public_id, options={})
81
- call_api("upload_large", options.merge(:resource_type=>:raw)) do
82
- params = {
83
- :timestamp=>Time.now.to_i,
84
- :type=>options[:type],
85
- :public_id=> public_id,
86
- :backup=>options[:backup],
87
- :final=>options[:final],
88
- :part_number=>options[:part_number],
89
- :upload_id=>options[:upload_id]
90
- }
91
- if file.is_a?(Pathname) || !file.respond_to?(:read)
92
- params[:file] = File.open(file, "rb")
93
- else
94
- params[:file] = file
95
- end
96
- [params, [:file]]
97
- end
98
- end
99
-
69
+ # Upload large raw files. Note that public_id should include an extension for best results.
70
+ def self.upload_large(file, public_id, options={})
71
+ if file.is_a?(Pathname) || !file.respond_to?(:read)
72
+ file = File.open(file, "rb")
73
+ end
74
+ upload = upload_id = nil
75
+ index = 1
76
+ while !file.eof?
77
+ buffer = file.read(20_000_000)
78
+ upload = upload_large_part(Cloudinary::Blob.new(buffer), public_id, options.merge(:upload_id=>upload_id, :part_number=>index, :final=>file.eof?))
79
+ upload_id = upload["upload_id"]
80
+ index += 1
81
+ end
82
+ upload
83
+ end
84
+
85
+
86
+ # Upload large raw files. Note that public_id should include an extension for best results.
87
+ def self.upload_large_part(file, public_id, options={})
88
+ call_api("upload_large", options.merge(:resource_type=>:raw)) do
89
+ params = {
90
+ :timestamp=>Time.now.to_i,
91
+ :type=>options[:type],
92
+ :public_id=> public_id,
93
+ :backup=>options[:backup],
94
+ :final=>options[:final],
95
+ :part_number=>options[:part_number],
96
+ :upload_id=>options[:upload_id]
97
+ }
98
+ if file.is_a?(Pathname) || !file.respond_to?(:read)
99
+ params[:file] = File.open(file, "rb")
100
+ else
101
+ params[:file] = file
102
+ end
103
+ [params, [:file]]
104
+ end
105
+ end
106
+
100
107
  def self.destroy(public_id, options={})
101
108
  call_api("destroy", options) do
102
109
  {
@@ -1,4 +1,4 @@
1
1
  # Copyright Cloudinary
2
2
  module Cloudinary
3
- VERSION = "1.0.68"
3
+ VERSION = "1.0.69"
4
4
  end
data/spec/api_spec.rb CHANGED
@@ -202,5 +202,59 @@ describe Cloudinary::Api do
202
202
  resource.should_not be_blank
203
203
  resource["derived"].length.should == 0
204
204
  end
205
+
206
+ it "should support setting manual moderation status" do
207
+ result = Cloudinary::Uploader.upload("spec/logo.png", {:moderation => :manual})
208
+ result["moderation"][0]["status"].should == "pending"
209
+ result["moderation"][0]["kind"].should == "manual"
210
+ api_result = Cloudinary::Api.update(result["public_id"], {:moderation_status => :approved})
211
+ api_result["moderation"][0]["status"].should == "approved"
212
+ api_result["moderation"][0]["kind"].should == "manual"
213
+ end
214
+
215
+ it "should support requesting ocr info" do
216
+ result = Cloudinary::Uploader.upload("spec/logo.png")
217
+ lambda{Cloudinary::Api.update(result["public_id"], {:ocr => :illegal})}.should raise_error(Cloudinary::Api::BadRequest, /^Illegal value/)
218
+ end
219
+
220
+ it "should support requesting raw conversion" do
221
+ result = Cloudinary::Uploader.upload("spec/docx.docx", :resource_type => :raw)
222
+ lambda{Cloudinary::Api.update(result["public_id"], {:resource_type => :raw, :raw_convert => :illegal})}.should raise_error(Cloudinary::Api::BadRequest, /^Illegal value/)
223
+ end
224
+
225
+ it "should support requesting categorization" do
226
+ result = Cloudinary::Uploader.upload("spec/logo.png")
227
+ lambda{Cloudinary::Api.update(result["public_id"], {:categorization => :illegal})}.should raise_error(Cloudinary::Api::BadRequest, /^Illegal value/)
228
+ end
229
+
230
+ it "should support requesting detection" do
231
+ result = Cloudinary::Uploader.upload("spec/logo.png")
232
+ lambda{Cloudinary::Api.update(result["public_id"], {:detection => :illegal})}.should raise_error(Cloudinary::Api::BadRequest, /^Illegal value/)
233
+ end
234
+
235
+ it "should support requesting ocr info" do
236
+ result = Cloudinary::Uploader.upload("spec/logo.png")
237
+ lambda{Cloudinary::Api.update(result["public_id"], {:auto_tagging => 0.5})}.should raise_error(Cloudinary::Api::BadRequest, /^Must use/)
238
+ end
239
+
240
+ it "should support listing by moderation kind and value" do
241
+ result1 = Cloudinary::Uploader.upload("spec/logo.png", {:moderation => :manual})
242
+ result2 = Cloudinary::Uploader.upload("spec/logo.png", {:moderation => :manual})
243
+ result3 = Cloudinary::Uploader.upload("spec/logo.png", {:moderation => :manual})
244
+ Cloudinary::Api.update(result1["public_id"], {:moderation_status => :approved})
245
+ Cloudinary::Api.update(result2["public_id"], {:moderation_status => :rejected})
246
+ approved = Cloudinary::Api.resources_by_moderation(:manual, :approved, :max_results => 1000)["resources"].map{|r| r["public_id"]}
247
+ approved.should include(result1["public_id"])
248
+ approved.should_not include(result2["public_id"])
249
+ approved.should_not include(result3["public_id"])
250
+ rejected = Cloudinary::Api.resources_by_moderation(:manual, :rejected, :max_results => 1000)["resources"].map{|r| r["public_id"]}
251
+ rejected.should include(result2["public_id"])
252
+ rejected.should_not include(result1["public_id"])
253
+ rejected.should_not include(result3["public_id"])
254
+ pending = Cloudinary::Api.resources_by_moderation(:manual, :pending, :max_results => 1000)["resources"].map{|r| r["public_id"]}
255
+ pending.should include(result3["public_id"])
256
+ pending.should_not include(result1["public_id"])
257
+ pending.should_not include(result2["public_id"])
258
+ end
205
259
 
206
260
  end
data/spec/docx.docx ADDED
Binary file
@@ -70,34 +70,34 @@ describe Cloudinary::Uploader do
70
70
  end
71
71
 
72
72
  it "should correctly handle unique_filename" do
73
- result = Cloudinary::Uploader.upload("spec/logo.png", use_filename: true)
73
+ result = Cloudinary::Uploader.upload("spec/logo.png", :use_filename => true)
74
74
  result["public_id"].should match(/logo_[a-zA-Z0-9]{6}/)
75
- result = Cloudinary::Uploader.upload("spec/logo.png", use_filename: true, unique_filename: false)
75
+ result = Cloudinary::Uploader.upload("spec/logo.png", :use_filename => true, :unique_filename => false)
76
76
  result["public_id"].should == "logo"
77
77
  end
78
78
 
79
79
  it "should allow whitelisted formats if allowed_formats", :allowed=>true do
80
- result = Cloudinary::Uploader.upload("spec/logo.png", allowed_formats: ["png"])
80
+ result = Cloudinary::Uploader.upload("spec/logo.png", :allowed_formats => ["png"])
81
81
  result["format"].should == "png"
82
82
  end
83
83
 
84
84
  it "should prevent non whitelisted formats from being uploaded if allowed_formats is specified", :allowed=>true do
85
- lambda{Cloudinary::Uploader.upload("spec/logo.png", allowed_formats: ["jpg"])}.should raise_error
85
+ lambda{Cloudinary::Uploader.upload("spec/logo.png", :allowed_formats => ["jpg"])}.should raise_error
86
86
  end
87
87
 
88
88
  it "should allow non whitelisted formats if type is specified and convert to that type", :allowed=>true do
89
- result = Cloudinary::Uploader.upload("spec/logo.png", allowed_formats: ["jpg"], format: "jpg")
89
+ result = Cloudinary::Uploader.upload("spec/logo.png", :allowed_formats => ["jpg"], :format => "jpg")
90
90
  result["format"].should == "jpg"
91
91
  end
92
92
 
93
93
  it "should allow sending face coordinates" do
94
94
  coordinates = [[120, 30, 109, 150], [121, 31, 110, 151]]
95
- result = Cloudinary::Uploader.upload("spec/logo.png", {face_coordinates: coordinates, faces: true})
95
+ result = Cloudinary::Uploader.upload("spec/logo.png", {:face_coordinates => coordinates, :faces => true})
96
96
  result["faces"].should == coordinates
97
97
 
98
98
  different_coordinates = [[122, 32, 111, 152]]
99
- Cloudinary::Uploader.explicit(result["public_id"], {face_coordinates: different_coordinates, faces: true, type: "upload"})
100
- info = Cloudinary::Api.resource(result["public_id"], {faces: true})
99
+ Cloudinary::Uploader.explicit(result["public_id"], {:face_coordinates => different_coordinates, :faces => true, :type => "upload"})
100
+ info = Cloudinary::Api.resource(result["public_id"], {:faces => true})
101
101
  info["faces"].should == different_coordinates
102
102
  end
103
103
 
@@ -107,4 +107,30 @@ describe Cloudinary::Uploader do
107
107
  info = Cloudinary::Api.resource(result["public_id"], {:context => true})
108
108
  info["context"].should == {"custom" => context}
109
109
  end
110
+
111
+ it "should support requesting manual moderation" do
112
+ result = Cloudinary::Uploader.upload("spec/logo.png", {:moderation => :manual})
113
+ result["moderation"][0]["status"].should == "pending"
114
+ result["moderation"][0]["kind"].should == "manual"
115
+ end
116
+
117
+ it "should support requesting ocr info" do
118
+ lambda{Cloudinary::Uploader.upload("spec/logo.png", {:ocr => :illegal})}.should raise_error(CloudinaryException, /Illegal value/)
119
+ end
120
+
121
+ it "should support requesting raw conversion" do
122
+ lambda{Cloudinary::Uploader.upload("spec/docx.docx", {:resource_type => :raw, :raw_convert => :illegal})}.should raise_error(CloudinaryException, /Illegal value/)
123
+ end
124
+
125
+ it "should support requesting categorization" do
126
+ lambda{Cloudinary::Uploader.upload("spec/logo.png", {:categorization => :illegal})}.should raise_error(CloudinaryException, /Illegal value/)
127
+ end
128
+
129
+ it "should support requesting detection" do
130
+ lambda{Cloudinary::Uploader.upload("spec/logo.png", {:detection => :illegal})}.should raise_error(CloudinaryException, /Illegal value/)
131
+ end
132
+
133
+ it "should support requesting auto_tagging" do
134
+ lambda{Cloudinary::Uploader.upload("spec/logo.png", {:auto_tagging => 0.5})}.should raise_error(CloudinaryException, /Must use/)
135
+ end
110
136
  end
data/spec/utils_spec.rb CHANGED
@@ -441,23 +441,23 @@ describe Cloudinary::Utils do
441
441
  end
442
442
 
443
443
  it "should correctly sign URLs", :signed => true do
444
- options = {version: 1234, transformation: {crop: "crop", width: 10, height: 20}, sign_url: true}
444
+ options = {:version => 1234, :transformation => {:crop => "crop", :width => 10, :height => 20}, :sign_url => true}
445
445
  expected = "http://res.cloudinary.com/test123/image/upload/s--MaRXzoEC--/c_crop,h_20,w_10/v1234/image.jpg"
446
446
  actual = Cloudinary::Utils.cloudinary_url("image.jpg", options)
447
447
  actual.should == expected
448
448
 
449
- options = {version: 1234, sign_url: true}
449
+ options = {:version => 1234, :sign_url => true}
450
450
  expected = "http://res.cloudinary.com/test123/image/upload/s--ZlgFLQcO--/v1234/image.jpg"
451
451
  actual = Cloudinary::Utils.cloudinary_url("image.jpg", options)
452
452
  actual.should == expected
453
453
 
454
- options = {transformation: {crop: "crop", width: 10, height: 20}, sign_url: true}
454
+ options = {:transformation => {:crop => "crop", :width => 10, :height => 20}, :sign_url => true}
455
455
  expected = "http://res.cloudinary.com/test123/image/upload/s--Ai4Znfl3--/c_crop,h_20,w_10/image.jpg"
456
456
  actual = Cloudinary::Utils.cloudinary_url("image.jpg", options)
457
457
  actual.should == expected
458
458
 
459
459
  expected = "http://res.cloudinary.com/test123/image/fetch/s--_GAUclyB--/v1234/http://google.com/path/to/image.png"
460
- actual = Cloudinary::Utils.cloudinary_url("http://google.com/path/to/image.png", type: "fetch", version: 1234, sign_url: true)
460
+ actual = Cloudinary::Utils.cloudinary_url("http://google.com/path/to/image.png", :type => "fetch", :version => 1234, :sign_url => true)
461
461
  actual.should == expected
462
462
  end
463
463
  end
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.0.68
4
+ version: 1.0.69
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2014-02-16 00:00:00.000000000 Z
14
+ date: 2014-02-25 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rest-client
@@ -101,6 +101,7 @@ files:
101
101
  - lib/cloudinary/version.rb
102
102
  - lib/tasks/cloudinary.rake
103
103
  - spec/api_spec.rb
104
+ - spec/docx.docx
104
105
  - spec/favicon.ico
105
106
  - spec/logo.png
106
107
  - spec/spec_helper.rb
@@ -145,6 +146,7 @@ specification_version: 3
145
146
  summary: Client library for easily using the Cloudinary service
146
147
  test_files:
147
148
  - spec/api_spec.rb
149
+ - spec/docx.docx
148
150
  - spec/favicon.ico
149
151
  - spec/logo.png
150
152
  - spec/spec_helper.rb