cloudinary 1.0.9 → 1.0.10

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,4 +1,4 @@
1
1
  pkg
2
2
  .project
3
3
  .rvmrc
4
-
4
+ assets/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Rakefile CHANGED
@@ -1,3 +1,8 @@
1
1
  require 'bundler'
2
2
  Bundler::GemHelper.install_tasks
3
3
 
4
+ task :fetch_assets do
5
+ system "/bin/rm -rf assets; mkdir -p assets; cd assets; curl -L https://github.com/cloudinary/cloudinary_js/tarball/master | tar zxvf - --strip=1"
6
+ end
7
+
8
+ task :build=>:fetch_assets
data/cloudinary.gemspec CHANGED
@@ -13,10 +13,11 @@ Gem::Specification.new do |s|
13
13
 
14
14
  s.rubyforge_project = "cloudinary"
15
15
 
16
- s.files = `git ls-files`.split("\n")
16
+ s.files = `git ls-files`.split("\n") + Dir.glob("assets/*/*")
17
17
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
 
21
21
  s.add_dependency "rest-client"
22
+ s.add_development_dependency "rspec"
22
23
  end
data/lib/cloudinary.rb CHANGED
@@ -5,7 +5,7 @@ require "cloudinary/utils"
5
5
  require "cloudinary/uploader"
6
6
  require "cloudinary/downloader"
7
7
  require "cloudinary/blob"
8
- require "cloudinary/static"
8
+ require "cloudinary/static" if defined?(::ActiveSupport)
9
9
  require 'active_support'
10
10
  require "cloudinary/missing"
11
11
  require "cloudinary/carrier_wave" if defined?(::CarrierWave)
@@ -1,6 +1,8 @@
1
1
  # Copyright Cloudinary
2
2
  require 'pp'
3
3
  module Cloudinary::CarrierWave
4
+ CLOUDINARY_PATH = /^([^\/]+)\/upload\/v(\d+)\/([^\/]+)#([^\/]+)$/
5
+
4
6
  class UploadError < StandardError
5
7
  attr_reader :http_code
6
8
  def initialize(message, http_code)
@@ -55,8 +57,40 @@ module Cloudinary::CarrierWave
55
57
  base.storage Cloudinary::CarrierWave::Storage
56
58
  base.extend ClassMethods
57
59
  base.send(:attr_accessor, :metadata)
60
+ base.send(:alias_method, :original_cache!, :cache!)
61
+ base.send(:alias_method, :original_cache_name, :cache_name)
62
+ base.send(:alias_method, :original_retrieve_from_cache!, :retrieve_from_cache!)
63
+ base.send(:include, Override)
58
64
  end
59
65
 
66
+ module Override
67
+ def cache!(new_file)
68
+ if new_file.is_a?(String) && new_file.match(CLOUDINARY_PATH)
69
+ @file = CloudinaryFile.new(new_file)
70
+ self.original_filename = @cache_id = @my_filename = @filename = @file.original_filename
71
+ else
72
+ original_cache!(new_file)
73
+ end
74
+ end
75
+
76
+ def retrieve_from_cache!(new_file)
77
+ if new_file.is_a?(String) && new_file.match(CLOUDINARY_PATH)
78
+ @file = CloudinaryFile.new(new_file)
79
+ self.original_filename = @cache_id = @my_filename = @filename = @file.original_filename
80
+ else
81
+ original_retrieve_from_cache!(new_file)
82
+ end
83
+ end
84
+
85
+ def cache_name
86
+ if @file.is_a?(CloudinaryFile)
87
+ return @file.to_s
88
+ else
89
+ return original_cache_name
90
+ end
91
+ end
92
+ end
93
+
60
94
  def set_or_yell(hash, attr, value)
61
95
  raise "conflicting transformation on #{attr} #{value}!=#{hash[attr]}" if hash[attr]
62
96
  hash[attr] = value
@@ -129,12 +163,13 @@ module Cloudinary::CarrierWave
129
163
  end
130
164
 
131
165
  def url(*args)
132
- if(args.first)
166
+ if args.first && !args.first.is_a?(Hash)
133
167
  super
134
168
  else
135
- return nil if blank?
136
- options = self.class.version_names.blank? ? {} : self.transformation
137
- Cloudinary::Utils.cloudinary_url(self.my_filename, options.clone)
169
+ return nil if self.my_identifier.blank?
170
+ options = args.extract_options!
171
+ options = options.merge(self.class.version_names.blank? ? {} : self.transformation)
172
+ Cloudinary::Utils.cloudinary_url(self.my_filename, options)
138
173
  end
139
174
  end
140
175
 
@@ -143,16 +178,17 @@ module Cloudinary::CarrierWave
143
178
  end
144
179
 
145
180
  def stored_filename
146
- @stored_filename ||= model.read_uploader(mounted_as)
181
+ @stored_filename = model.read_uploader(mounted_as) if @stored_filename.blank?
182
+ @stored_filename
147
183
  end
148
184
 
149
185
  def my_filename
150
- @my_filename ||= stored_filename || ("#{self.public_id}.#{self.format}")
186
+ @my_filename ||= stored_filename.present? ? stored_filename : ("#{self.public_id}.#{self.format}")
151
187
  end
152
188
 
153
189
  def public_id
154
190
  return @public_id if @public_id
155
- if stored_filename
191
+ if stored_filename.present?
156
192
  last_dot = stored_filename.rindex(".")
157
193
  @public_id = last_dot ? stored_filename[0, last_dot] : stored_filename
158
194
  end
@@ -165,8 +201,18 @@ module Cloudinary::CarrierWave
165
201
  @file = RemoteFile.new(uri, @filename)
166
202
  end
167
203
 
168
- def blank?
169
- self.filename.blank? && self.stored_filename.blank?
204
+ def my_identifier
205
+ (self.filename || self.stored_filename.present?) ? self.my_filename : nil
206
+ end
207
+
208
+ class RemoveableFile
209
+ def initialize(identifier)
210
+ @public_id = identifier.split("/").last.split(".").first
211
+ end
212
+
213
+ def delete
214
+ Cloudinary::Uploader.destroy(@public_id)
215
+ end
170
216
  end
171
217
 
172
218
  class RemoteFile
@@ -181,10 +227,33 @@ module Cloudinary::CarrierWave
181
227
  end
182
228
  end
183
229
 
230
+ class CloudinaryFile
231
+ attr_reader :original_filename, :version
232
+ def initialize(file_info)
233
+ resource_type, @version, @original_filename, @signature = file_info.scan(CLOUDINARY_PATH).first
234
+ raise "Cloudinary CarrierWave integration supports images only" if resource_type != "image"
235
+ public_id = @original_filename[0..(@original_filename.rindex(".")-1)]
236
+ expected_signature = Cloudinary::Utils.api_sign_request({:public_id=>public_id, :version=>version}, Cloudinary.config.api_secret)
237
+ if @signature != expected_signature
238
+ raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.cloudinary_signature_error", :public_id=>public_id, :default=>"Invalid signature for #{public_id}")
239
+ end
240
+ end
241
+
242
+ def to_s
243
+ "image/upload/v#{@version}/#{@original_filename}##{@signature}"
244
+ end
245
+
246
+ def delete
247
+ # Do nothing. This is a virtual file.
248
+ end
249
+ end
250
+
184
251
  class Storage < ::CarrierWave::Storage::Abstract
185
252
  def store!(file)
186
253
  # Moved to identifier...
187
254
  if uploader.class.version_names.blank?
255
+ return store_cloudinary_version(file.version) if file.is_a?(CloudinaryFile)
256
+
188
257
  # This is the toplevel, need to upload the actual file.
189
258
  params = uploader.transformation.dup
190
259
  params[:return_error] = true
@@ -206,35 +275,41 @@ module Cloudinary::CarrierWave
206
275
  raise UploadError.new(uploader.metadata["error"]["message"], uploader.metadata["error"]["http_code"])
207
276
  end
208
277
 
209
- if uploader.metadata["version"]
210
-
211
- name = "v#{uploader.metadata["version"]}/#{identifier.split("/").last}"
212
- model_class = uploader.model.class
213
- if defined?(ActiveRecord::Base) && uploader.model.is_a?(ActiveRecord::Base)
214
- primary_key = model_class.primary_key.to_sym
215
- model_class.update_all({uploader.mounted_as=>name}, {primary_key=>uploader.model.send(primary_key)})
216
- uploader.model.send :write_attribute, uploader.mounted_as, name
217
- elsif model_class.respond_to?(:update_all) && uploader.model.respond_to?(:_id)
218
- # Mongoid support
219
- model_class.where(:_id=>uploader.model._id).update_all(uploader.mounted_as=>name)
220
- uploader.model.send :write_attribute, uploader.mounted_as, name
221
- else
222
- raise "Only ActiveRecord and Mongoid are supported at the moment!"
223
- end
224
- end
278
+ store_cloudinary_version(uploader.metadata["version"]) if uploader.metadata["version"]
225
279
  # Will throw an exception on error
226
280
  else
227
281
  raise "nested versions are not allowed." if (uploader.class.version_names.length > 1)
228
282
  # Do nothing
229
283
  end
284
+ nil
285
+ end
286
+
287
+ def store_cloudinary_version(version)
288
+ name = "v#{version}/#{identifier.split("/").last}"
289
+ model_class = uploader.model.class
290
+ if defined?(ActiveRecord::Base) && uploader.model.is_a?(ActiveRecord::Base)
291
+ primary_key = model_class.primary_key.to_sym
292
+ model_class.update_all({uploader.mounted_as=>name}, {primary_key=>uploader.model.send(primary_key)})
293
+ uploader.model.send :write_attribute, uploader.mounted_as, name
294
+ elsif model_class.respond_to?(:update_all) && uploader.model.respond_to?(:_id)
295
+ # Mongoid support
296
+ model_class.where(:_id=>uploader.model._id).update_all(uploader.mounted_as=>name)
297
+ uploader.model.send :write_attribute, uploader.mounted_as, name
298
+ else
299
+ raise "Only ActiveRecord and Mongoid are supported at the moment!"
300
+ end
230
301
  end
231
302
 
232
303
  def retrieve!(identifier)
233
- # Do nothing
304
+ if uploader.class.version_names.blank?
305
+ return RemoveableFile.new(identifier)
306
+ else
307
+ return nil # Version files should not be deleted.
308
+ end
234
309
  end
235
310
 
236
311
  def identifier
237
- (uploader.filename || uploader.stored_filename) ? uploader.my_filename : nil
312
+ uploader.my_identifier
238
313
  end
239
314
  end
240
315
  end
@@ -81,12 +81,9 @@ module CloudinaryHelper
81
81
  form_options[:method] = :post
82
82
  form_options[:multipart] = true
83
83
 
84
- options[:timestamp] = Time.now.to_i
85
- options[:callback] = callback_url
86
- options[:transformation] = Cloudinary::Utils.generate_transformation_string(options[:transformation]) if options[:transformation]
87
- options[:tags] = Cloudinary::Utils.build_array(options[:tags]).join(",") if options[:tags]
88
- options[:signature] = Cloudinary::Utils.api_sign_request(options, Cloudinary.config.api_secret)
89
- options[:api_key] = Cloudinary.config.api_key
84
+ params = Cloudinary::Uploader.build_upload_params(options.merge(:callback=>callback_url))
85
+ params[:signature] = Cloudinary::Utils.api_sign_request(params, Cloudinary.config.api_secret)
86
+ params[:api_key] = Cloudinary.config.api_key
90
87
 
91
88
  api_url = Cloudinary::Utils.cloudinary_api_url("upload",
92
89
  {:resource_type => options.delete(:resource_type), :upload_prefix => options.delete(:upload_prefix)})
@@ -94,7 +91,7 @@ module CloudinaryHelper
94
91
  form_tag(api_url, form_options) do
95
92
  content = []
96
93
 
97
- options.each do |name, value|
94
+ params.each do |name, value|
98
95
  content << hidden_field_tag(name, value)
99
96
  end
100
97
 
@@ -104,10 +101,67 @@ module CloudinaryHelper
104
101
  end
105
102
  end
106
103
 
104
+ CLOUDINARY_JS_CONFIG_PARAMS = [:api_key, :cloud_name, :private_cdn, :secure_distribution, :cdn_subdomain]
105
+ def cloudinary_js_config
106
+ params = {}
107
+ CLOUDINARY_JS_CONFIG_PARAMS.each{|param| params[param] = Cloudinary.config.send(param)}
108
+ content_tag("script", "$.cloudinary.config(#{params.to_json});".html_safe, :type=>"text/javascript")
109
+ end
110
+
107
111
  def cloudinary_url(source, options = {})
108
112
  options[:secure] = request.ssl? if !options.include?(:secure) && defined?(request) && request && request.respond_to?(:ssl?)
109
113
  Cloudinary::Utils.cloudinary_url(source, options)
110
114
  end
115
+
116
+ def cl_image_upload(object_name, method, options={})
117
+ cl_image_upload_tag("#{object_name}[#{method}]", options)
118
+ end
119
+
120
+ def cl_image_upload_tag(field, options={})
121
+ html_options = options.delete(:html) || {}
122
+ cloudinary_upload_url = Cloudinary::Utils.cloudinary_api_url("upload", {:resource_type=>:auto}.merge(options))
123
+
124
+ api_key = options[:api_key] || Cloudinary.config.api_key || raise("Must supply api_key")
125
+ api_secret = options[:api_secret] || Cloudinary.config.api_secret || raise("Must supply api_secret")
126
+
127
+ cloudinary_params = Cloudinary::Uploader.build_upload_params(options)
128
+ cloudinary_params[:callback] = build_callback_url(options)
129
+ cloudinary_params[:signature] = Cloudinary::Utils.api_sign_request(cloudinary_params, api_secret)
130
+ cloudinary_params[:api_key] = api_key
131
+
132
+ tag_options = html_options.merge(:type=>"file", :name=>"file",
133
+ :"data-url"=>cloudinary_upload_url,
134
+ :"data-form-data"=>cloudinary_params.reject{|k, v| v.blank?}.to_json,
135
+ :"data-cloudinary-field"=>field,
136
+ :"class" => [html_options[:class], "cloudinary-fileupload"].flatten.compact
137
+ ).reject{|k,v| v.blank?}
138
+ content_tag("input", nil, tag_options)
139
+ end
140
+
141
+ def self.included(base)
142
+ ActionView::Helpers::FormBuilder.send(:include, Cloudinary::FormBuilder)
143
+ end
144
+
145
+ private
146
+ def build_callback_url(options)
147
+ callback_path = options.delete(:callback_cors) || Cloudinary.config.callback_cors || "/cloudinary_cors.html"
148
+ if !callback_path.match(/^https?:\/\//)
149
+ callback_url = request.scheme + "://"
150
+ callback_url << request.host
151
+ if request.scheme == "https" && request.port != 443 ||
152
+ request.scheme == "http" && request.port != 80
153
+ callback_url << ":#{request.port}"
154
+ end
155
+ callback_url << callback_path
156
+ end
157
+ callback_url
158
+ end
159
+ end
160
+
161
+ module Cloudinary::FormBuilder
162
+ def cl_image_upload(method, options={})
163
+ @template.cl_image_upload(@object_name, method, objectify_options(options))
164
+ end
111
165
  end
112
166
 
113
167
  ActionView::Base.send :include, CloudinaryHelper
@@ -9,7 +9,7 @@ class Cloudinary::Static
9
9
  def self.discover
10
10
  ignore_files = Cloudinary.config.ignore_files || IGNORE_FILES
11
11
  relative_dirs = Cloudinary.config.statis_image_dirs || STATIC_IMAGE_DIRS
12
- dirs = relative_dirs.map{|dir| Rails.root.join(dir)}.select(&:exist?)
12
+ dirs = relative_dirs.map{|dir| self.root.join(dir)}.select(&:exist?)
13
13
  dirs.each do
14
14
  |dir|
15
15
  dir.find do
@@ -23,7 +23,7 @@ class Cloudinary::Static
23
23
  elsif SUPPORTED_IMAGES.none?{|pattern| pattern.is_a?(String) ? pattern == file : file.match(pattern)}
24
24
  next
25
25
  else
26
- relative_path = path.relative_path_from(Rails.root)
26
+ relative_path = path.relative_path_from(self.root)
27
27
  public_path = path.relative_path_from(dir.dirname)
28
28
  yield(relative_path, public_path)
29
29
  end
@@ -33,12 +33,16 @@ class Cloudinary::Static
33
33
 
34
34
  UTC = ActiveSupport::TimeZone["UTC"]
35
35
 
36
+ def self.root
37
+ defined?(Rails) ? Rails.root : Pathname.new(".")
38
+ end
39
+
36
40
  def self.metadata_file_path
37
- Rails.root.join(METADATA_FILE)
41
+ self.root.join(METADATA_FILE)
38
42
  end
39
43
 
40
44
  def self.metadata_trash_file_path
41
- Rails.root.join(METADATA_TRASH_FILE)
45
+ self.root.join(METADATA_TRASH_FILE)
42
46
  end
43
47
 
44
48
  def self.metadata(metadata_file = metadata_file_path, hash=true)
@@ -73,7 +77,7 @@ class Cloudinary::Static
73
77
  |path, public_path|
74
78
  next if found_paths.include?(path)
75
79
  found_paths << path
76
- data = Rails.root.join(path).read(:mode=>"rb")
80
+ data = self.root.join(path).read(:mode=>"rb")
77
81
  ext = path.extname
78
82
  format = ext[1..-1]
79
83
  md5 = Digest::MD5.hexdigest(data)
@@ -4,23 +4,28 @@ require 'json'
4
4
 
5
5
  class Cloudinary::Uploader
6
6
 
7
+ def self.build_upload_params(options)
8
+ params = {:timestamp=>Time.now.to_i,
9
+ :transformation => Cloudinary::Utils.generate_transformation_string(options),
10
+ :public_id=> options[:public_id],
11
+ :callback=> options[:callback],
12
+ :format=>options[:format],
13
+ :type=>options[:type],
14
+ :tags=>options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(",")}
15
+ if options[:eager]
16
+ params[:eager] = options[:eager].map do
17
+ |transformation, format|
18
+ transformation = transformation.clone
19
+ format = transformation.delete(:format) || format
20
+ [Cloudinary::Utils.generate_transformation_string(transformation), format].compact.join("/")
21
+ end.join("|")
22
+ end
23
+ params
24
+ end
25
+
7
26
  def self.upload(file, options={})
8
27
  call_api("upload", options) do
9
- params = {:timestamp=>Time.now.to_i,
10
- :transformation => Cloudinary::Utils.generate_transformation_string(options),
11
- :public_id=> options[:public_id],
12
- :callback=> options[:callback],
13
- :format=>options[:format],
14
- :type=>options[:type],
15
- :tags=>options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(",")}
16
- if options[:eager]
17
- params[:eager] = options[:eager].map do
18
- |transformation, format|
19
- transformation = transformation.clone
20
- format = transformation.delete(:format) || format
21
- [Cloudinary::Utils.generate_transformation_string(transformation), format].compact.join("/")
22
- end.join("|")
23
- end
28
+ params = build_upload_params(options)
24
29
  if file.respond_to?(:read) || file =~ /^https?:/
25
30
  params[:file] = file
26
31
  else
@@ -7,10 +7,10 @@ class Cloudinary::Utils
7
7
 
8
8
  # Warning: options are being destructively updated!
9
9
  def self.generate_transformation_string(options={})
10
+ size = options.delete(:size)
11
+ options[:width], options[:height] = size.split("x") if size
10
12
  width = options[:width]
11
13
  height = options[:height]
12
- size = options.delete(:size)
13
- width, height = size.split("x") if size
14
14
  options.delete(:width) if width && width.to_f < 1
15
15
  options.delete(:height) if height && height.to_f < 1
16
16
 
@@ -71,7 +71,7 @@ class Cloudinary::Utils
71
71
  return source
72
72
  end
73
73
  end
74
- @metadata ||= Cloudinary::Static.metadata
74
+ @metadata ||= defined?(Cloudinary::Static) ? Cloudinary::Static.metadata : {}
75
75
  if @metadata["images/#{source}"]
76
76
  return source if !Cloudinary.config.static_image_support
77
77
  type = :asset
@@ -1,4 +1,4 @@
1
1
  # Copyright Cloudinary
2
2
  module Cloudinary
3
- VERSION = "1.0.9"
3
+ VERSION = "1.0.10"
4
4
  end
@@ -0,0 +1,11 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper.rb"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+ end
@@ -0,0 +1,169 @@
1
+ require 'spec_helper'
2
+ require 'cloudinary'
3
+
4
+ describe Cloudinary::Utils do
5
+ before(:each) do
6
+ Cloudinary.config do
7
+ |config|
8
+ config.cloud_name = "test123"
9
+ config.secure_distribution = nil
10
+ config.private_cdn = false
11
+ end
12
+ end
13
+
14
+ it "should use cloud_name from config" do
15
+ result = Cloudinary::Utils.cloudinary_url("test")
16
+ result.should == "http://res.cloudinary.com/test123/image/upload/test"
17
+ end
18
+
19
+ it "should allow overriding cloud_name in options" do
20
+ options = {:cloud_name=>"test321"}
21
+ result = Cloudinary::Utils.cloudinary_url("test", options)
22
+ options.should == {}
23
+ result.should == "http://res.cloudinary.com/test321/image/upload/test"
24
+ end
25
+
26
+ it "should use default secure distribution if secure=true" do
27
+ options = {:secure=>true}
28
+ result = Cloudinary::Utils.cloudinary_url("test", options)
29
+ options.should == {}
30
+ result.should == "https://d3jpl91pxevbkh.cloudfront.net/test123/image/upload/test"
31
+ end
32
+
33
+ it "should allow overriding secure distribution if secure=true" do
34
+ options = {:secure=>true, :secure_distribution=>"something.else.com"}
35
+ result = Cloudinary::Utils.cloudinary_url("test", options)
36
+ options.should == {}
37
+ result.should == "https://something.else.com/test123/image/upload/test"
38
+ end
39
+
40
+ it "should take secure distribution from config if secure=true" do
41
+ Cloudinary.config.secure_distribution = "config.secure.distribution.com"
42
+ options = {:secure=>true}
43
+ result = Cloudinary::Utils.cloudinary_url("test", options)
44
+ options.should == {}
45
+ result.should == "https://config.secure.distribution.com/test123/image/upload/test"
46
+ end
47
+
48
+ it "should raise exception if secure is given with private_cdn and no secure_distribution" do
49
+ Cloudinary.config.private_cdn = true
50
+ lambda {Cloudinary::Utils.cloudinary_url("test", :secure=>true)}.should raise_error
51
+ end
52
+
53
+ it "should use format from options" do
54
+ options = {:format=>:jpg}
55
+ result = Cloudinary::Utils.cloudinary_url("test", options)
56
+ options.should == {}
57
+ result.should == "http://res.cloudinary.com/test123/image/upload/test.jpg"
58
+ end
59
+
60
+ it "should use width and height from options only if crop is given" do
61
+ options = {:width=>100, :height=>100}
62
+ result = Cloudinary::Utils.cloudinary_url("test", options)
63
+ result.should == "http://res.cloudinary.com/test123/image/upload/test"
64
+ options.should == {:width=>100, :height=>100}
65
+ options = {:width=>100, :height=>100, :crop=>:crop}
66
+ result = Cloudinary::Utils.cloudinary_url("test", options)
67
+ options.should == {:width=>100, :height=>100}
68
+ result.should == "http://res.cloudinary.com/test123/image/upload/c_crop,h_100,w_100/test"
69
+ end
70
+
71
+ it "should use x, y, radius, prefix, gravity and quality from options" do
72
+ options = {:x=>1, :y=>2, :radius=>3, :gravity=>:center, :quality=>0.4, :prefix=>"a"}
73
+ result = Cloudinary::Utils.cloudinary_url("test", options)
74
+ options.should == {}
75
+ result.should == "http://res.cloudinary.com/test123/image/upload/g_center,p_a,q_0.4,r_3,x_1,y_2/test"
76
+ end
77
+
78
+ it "should support named tranformation" do
79
+ options = {:transformation=>"blip"}
80
+ result = Cloudinary::Utils.cloudinary_url("test", options)
81
+ options.should == {}
82
+ result.should == "http://res.cloudinary.com/test123/image/upload/t_blip/test"
83
+ end
84
+
85
+ it "should support array of named tranformations" do
86
+ options = {:transformation=>["blip", "blop"]}
87
+ result = Cloudinary::Utils.cloudinary_url("test", options)
88
+ options.should == {}
89
+ result.should == "http://res.cloudinary.com/test123/image/upload/t_blip.blop/test"
90
+ end
91
+
92
+ it "should support base tranformation" do
93
+ options = {:transformation=>{:x=>100, :y=>100, :crop=>:fill}, :crop=>:crop, :width=>100}
94
+ result = Cloudinary::Utils.cloudinary_url("test", options)
95
+ options.should == {:width=>100}
96
+ result.should == "http://res.cloudinary.com/test123/image/upload/c_fill,x_100,y_100/c_crop,w_100/test"
97
+ end
98
+
99
+ it "should support array of base tranformations" do
100
+ options = {:transformation=>[{:x=>100, :y=>100, :width=>200, :crop=>:fill}, {:radius=>10}], :crop=>:crop, :width=>100}
101
+ result = Cloudinary::Utils.cloudinary_url("test", options)
102
+ options.should == {:width=>100}
103
+ result.should == "http://res.cloudinary.com/test123/image/upload/c_fill,w_200,x_100,y_100/r_10/c_crop,w_100/test"
104
+ end
105
+
106
+ it "should not include empty tranformations" do
107
+ options = {:transformation=>[{}, {:x=>100, :y=>100, :crop=>:fill}, {}]}
108
+ result = Cloudinary::Utils.cloudinary_url("test", options)
109
+ options.should == {}
110
+ result.should == "http://res.cloudinary.com/test123/image/upload/c_fill,x_100,y_100/test"
111
+ end
112
+
113
+ it "should support size" do
114
+ options = {:size=>"10x10", :crop=>:crop}
115
+ result = Cloudinary::Utils.cloudinary_url("test", options)
116
+ options.should == {:width=>"10", :height=>"10"}
117
+ result.should == "http://res.cloudinary.com/test123/image/upload/c_crop,h_10,w_10/test"
118
+ end
119
+
120
+ it "should use type from options" do
121
+ options = {:type=>:facebook}
122
+ result = Cloudinary::Utils.cloudinary_url("test", options)
123
+ options.should == {}
124
+ result.should == "http://res.cloudinary.com/test123/image/facebook/test"
125
+ end
126
+
127
+ it "should use resource_type from options" do
128
+ options = {:resource_type=>:raw}
129
+ result = Cloudinary::Utils.cloudinary_url("test", options)
130
+ options.should == {}
131
+ result.should == "http://res.cloudinary.com/test123/raw/upload/test"
132
+ end
133
+
134
+ it "should ignore http links only if type is not given or is asset" do
135
+ options = {:type=>nil}
136
+ result = Cloudinary::Utils.cloudinary_url("http://test", options)
137
+ options.should == {}
138
+ result.should == "http://test"
139
+ options = {:type=>:asset}
140
+ result = Cloudinary::Utils.cloudinary_url("http://test", options)
141
+ options.should == {}
142
+ result.should == "http://test"
143
+ options = {:type=>:fetch}
144
+ result = Cloudinary::Utils.cloudinary_url("http://test", options)
145
+ options.should == {}
146
+ result.should == "http://res.cloudinary.com/test123/image/fetch/http://test"
147
+ end
148
+
149
+ it "should use allow absolute links to /images" do
150
+ options = {}
151
+ result = Cloudinary::Utils.cloudinary_url("/images/test", options)
152
+ options.should == {}
153
+ result.should == "http://res.cloudinary.com/test123/image/upload/test"
154
+ end
155
+
156
+ it "should use ignore absolute links not to /images" do
157
+ options = {}
158
+ result = Cloudinary::Utils.cloudinary_url("/js/test", options)
159
+ options.should == {}
160
+ result.should == "/js/test"
161
+ end
162
+
163
+ it "should escape fetch urls" do
164
+ options = {:type=>:fetch}
165
+ result = Cloudinary::Utils.cloudinary_url("http://blah.com/hello?a=b", options)
166
+ options.should == {}
167
+ result.should == "http://res.cloudinary.com/test123/image/fetch/http://blah.com/hello%3Fa%3Db"
168
+ end
169
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: cloudinary
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.0.9
5
+ version: 1.0.10
6
6
  platform: ruby
7
7
  authors:
8
8
  - Nadav Soferman
@@ -12,7 +12,7 @@ autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
14
 
15
- date: 2012-04-16 00:00:00 +03:00
15
+ date: 2012-04-18 00:00:00 +03:00
16
16
  default_executable:
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
@@ -26,6 +26,17 @@ dependencies:
26
26
  version: "0"
27
27
  type: :runtime
28
28
  version_requirements: *id001
29
+ - !ruby/object:Gem::Dependency
30
+ name: rspec
31
+ prerelease: false
32
+ requirement: &id002 !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: "0"
38
+ type: :development
39
+ version_requirements: *id002
29
40
  description: Client library for easily using the Cloudinary service
30
41
  email:
31
42
  - nadav.soferman@cloudinary.com
@@ -39,6 +50,7 @@ extra_rdoc_files: []
39
50
 
40
51
  files:
41
52
  - .gitignore
53
+ - .rspec
42
54
  - Gemfile
43
55
  - README.md
44
56
  - Rakefile
@@ -57,6 +69,13 @@ files:
57
69
  - lib/cloudinary/utils.rb
58
70
  - lib/cloudinary/version.rb
59
71
  - lib/tasks/cloudinary.rake
72
+ - spec/spec_helper.rb
73
+ - spec/utils_spec.rb
74
+ - assets/html/cloudinary_cors.html
75
+ - assets/js/jquery.cloudinary.js
76
+ - assets/js/jquery.fileupload.js
77
+ - assets/js/jquery.iframe-transport.js
78
+ - assets/js/jquery.ui.widget.js
60
79
  has_rdoc: true
61
80
  homepage: http://cloudinary.com
62
81
  licenses: []
@@ -85,5 +104,6 @@ rubygems_version: 1.6.2
85
104
  signing_key:
86
105
  specification_version: 3
87
106
  summary: Client library for easily using the Cloudinary service
88
- test_files: []
89
-
107
+ test_files:
108
+ - spec/spec_helper.rb
109
+ - spec/utils_spec.rb