cloudinary 1.13.0 → 1.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +42 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
  4. data/CHANGELOG.md +61 -0
  5. data/Rakefile +3 -45
  6. data/cloudinary.gemspec +17 -4
  7. data/lib/active_storage/service/cloudinary_service.rb +44 -10
  8. data/lib/cloudinary.rb +22 -18
  9. data/lib/cloudinary/api.rb +3 -2
  10. data/lib/cloudinary/carrier_wave.rb +1 -0
  11. data/lib/cloudinary/carrier_wave/remote.rb +2 -2
  12. data/lib/cloudinary/carrier_wave/storage.rb +2 -1
  13. data/lib/cloudinary/cloudinary_controller.rb +2 -4
  14. data/lib/cloudinary/railtie.rb +7 -3
  15. data/lib/cloudinary/uploader.rb +6 -2
  16. data/lib/cloudinary/utils.rb +13 -10
  17. data/lib/cloudinary/version.rb +1 -1
  18. data/lib/tasks/cloudinary/fetch_assets.rake +48 -0
  19. data/lib/tasks/{cloudinary.rake → cloudinary/sync_static.rake} +0 -0
  20. data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +6 -5
  21. metadata +13 -192
  22. data/spec/access_control_spec.rb +0 -102
  23. data/spec/active_storage/Gemfile +0 -12
  24. data/spec/active_storage/application_system_test_case.rb +0 -5
  25. data/spec/active_storage/database/create_users_migration.rb +0 -9
  26. data/spec/active_storage/database/setup.rb +0 -7
  27. data/spec/active_storage/dummy/Rakefile +0 -5
  28. data/spec/active_storage/dummy/app/assets/config/manifest.js +0 -3
  29. data/spec/active_storage/dummy/app/assets/javascripts/application.js +0 -13
  30. data/spec/active_storage/dummy/app/assets/stylesheets/application.css +0 -15
  31. data/spec/active_storage/dummy/app/controllers/application_controller.rb +0 -5
  32. data/spec/active_storage/dummy/app/helpers/application_helper.rb +0 -4
  33. data/spec/active_storage/dummy/app/jobs/application_job.rb +0 -4
  34. data/spec/active_storage/dummy/app/models/application_record.rb +0 -5
  35. data/spec/active_storage/dummy/app/views/layouts/application.html.erb +0 -14
  36. data/spec/active_storage/dummy/bin/bundle +0 -5
  37. data/spec/active_storage/dummy/bin/rails +0 -6
  38. data/spec/active_storage/dummy/bin/rake +0 -6
  39. data/spec/active_storage/dummy/bin/yarn +0 -11
  40. data/spec/active_storage/dummy/config.ru +0 -7
  41. data/spec/active_storage/dummy/config/application.rb +0 -22
  42. data/spec/active_storage/dummy/config/boot.rb +0 -7
  43. data/spec/active_storage/dummy/config/database.yml +0 -25
  44. data/spec/active_storage/dummy/config/environment.rb +0 -7
  45. data/spec/active_storage/dummy/config/environments/development.rb +0 -52
  46. data/spec/active_storage/dummy/config/environments/production.rb +0 -83
  47. data/spec/active_storage/dummy/config/environments/test.rb +0 -38
  48. data/spec/active_storage/dummy/config/initializers/application_controller_renderer.rb +0 -7
  49. data/spec/active_storage/dummy/config/initializers/assets.rb +0 -16
  50. data/spec/active_storage/dummy/config/initializers/backtrace_silencers.rb +0 -8
  51. data/spec/active_storage/dummy/config/initializers/cookies_serializer.rb +0 -7
  52. data/spec/active_storage/dummy/config/initializers/filter_parameter_logging.rb +0 -6
  53. data/spec/active_storage/dummy/config/initializers/inflections.rb +0 -17
  54. data/spec/active_storage/dummy/config/initializers/mime_types.rb +0 -5
  55. data/spec/active_storage/dummy/config/initializers/wrap_parameters.rb +0 -16
  56. data/spec/active_storage/dummy/config/routes.rb +0 -4
  57. data/spec/active_storage/dummy/config/secrets.yml +0 -32
  58. data/spec/active_storage/dummy/config/spring.rb +0 -8
  59. data/spec/active_storage/dummy/config/storage.yml +0 -3
  60. data/spec/active_storage/dummy/config/webpacker.yml +0 -72
  61. data/spec/active_storage/dummy/package.json +0 -5
  62. data/spec/active_storage/dummy/public/404.html +0 -67
  63. data/spec/active_storage/dummy/public/422.html +0 -67
  64. data/spec/active_storage/dummy/public/500.html +0 -66
  65. data/spec/active_storage/dummy/public/apple-touch-icon-precomposed.png +0 -0
  66. data/spec/active_storage/dummy/public/apple-touch-icon.png +0 -0
  67. data/spec/active_storage/dummy/public/favicon.ico +0 -0
  68. data/spec/active_storage/fixtures/files/colors.bmp +0 -0
  69. data/spec/active_storage/fixtures/files/empty_file.txt +0 -0
  70. data/spec/active_storage/fixtures/files/favicon.ico +0 -0
  71. data/spec/active_storage/fixtures/files/icon.psd +0 -0
  72. data/spec/active_storage/fixtures/files/icon.svg +0 -13
  73. data/spec/active_storage/fixtures/files/image.gif +0 -0
  74. data/spec/active_storage/fixtures/files/racecar.jpg +0 -0
  75. data/spec/active_storage/fixtures/files/racecar.tif +0 -0
  76. data/spec/active_storage/fixtures/files/racecar_rotated.jpg +0 -0
  77. data/spec/active_storage/fixtures/files/report.pdf +0 -0
  78. data/spec/active_storage/fixtures/files/rotated_video.mp4 +0 -0
  79. data/spec/active_storage/fixtures/files/video.mp4 +0 -0
  80. data/spec/active_storage/fixtures/files/video_with_rectangular_samples.mp4 +0 -0
  81. data/spec/active_storage/fixtures/files/video_with_undefined_display_aspect_ratio.mp4 +0 -0
  82. data/spec/active_storage/fixtures/files/video_without_video_stream.mp4 +0 -0
  83. data/spec/active_storage/service/cloudinary_service_spec.rb +0 -107
  84. data/spec/active_storage/service/configurations.yml +0 -4
  85. data/spec/active_storage/test_helper.rb +0 -43
  86. data/spec/api_spec.rb +0 -623
  87. data/spec/archive_spec.rb +0 -145
  88. data/spec/auth_token_spec.rb +0 -77
  89. data/spec/cache_spec.rb +0 -109
  90. data/spec/cloudinary_helper_spec.rb +0 -327
  91. data/spec/cloudinary_spec.rb +0 -56
  92. data/spec/data/sync_static/app/assets/javascripts/1.coffee +0 -1
  93. data/spec/data/sync_static/app/assets/javascripts/1.js +0 -1
  94. data/spec/data/sync_static/app/assets/stylesheets/1.css +0 -3
  95. data/spec/docx.docx +0 -0
  96. data/spec/favicon.ico +0 -0
  97. data/spec/image_spec.rb +0 -107
  98. data/spec/logo.png +0 -0
  99. data/spec/movie.mp4 +0 -0
  100. data/spec/rake_spec.rb +0 -160
  101. data/spec/sample_asset_file.tsv +0 -4
  102. data/spec/search_spec.rb +0 -109
  103. data/spec/spec_helper.rb +0 -273
  104. data/spec/storage_spec.rb +0 -44
  105. data/spec/streaminig_profiles_api_spec.rb +0 -74
  106. data/spec/support/helpers/temp_file_helpers.rb +0 -22
  107. data/spec/support/shared_contexts/rake.rb +0 -19
  108. data/spec/uploader_spec.rb +0 -409
  109. data/spec/utils_methods_spec.rb +0 -81
  110. data/spec/utils_spec.rb +0 -1052
  111. data/spec/video_tag_spec.rb +0 -253
  112. data/spec/video_url_spec.rb +0 -185
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2e5827b8b849956cb26923c951ff72b205ff34e898309513ec1a18eca3abd47f
4
- data.tar.gz: 53acb20dcbd39a0dfa3d99c912c128e0731950893066a102bda1e4d267c1ebc2
3
+ metadata.gz: 38bfe3ef22f15b588b0cc8d80a433eb76d31b899eed350a8722547eeeee86643
4
+ data.tar.gz: f00c4f2e455a3ef278a5169df4fd40f982e65f774ccd444095053663dc531c15
5
5
  SHA512:
6
- metadata.gz: efd2057b536c8bbd339efce5046e23a1ee9d8c35cd398354f1ec3d72dcb98f9f2c0d7696441097b9e9de576dd98ae97c594e0368937f9ff60a52c5cd6556e98a
7
- data.tar.gz: 19215c9db03f24c24b24aabfaf1bb887eaac5bd2c493890e2426a8523503c3235de85be0a3a243ce2ac31b52c8463f5ce4ef7f1db5775a06082436dc1610baca
6
+ metadata.gz: 560784ae8664c5d3425599cb40cd72f69010223a22ae8d62dbb0c16033ce25dc28ae5810f39adb859436209d767dbfbe097974f7f8018add701eb072556e5bb3
7
+ data.tar.gz: 551b473e18bb1774a724da52201c8a8d463cb7dcaaa3926de8f980b150fb18e69c03d50d39fa6e9d11d2d8f29d1413759953d714166252c6390e08ad5811c668
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: Bug report
3
+ about: Bug report for Cloudinary Ruby SDK
4
+ title: ''
5
+ labels: ''
6
+ assignees: const-cloudinary
7
+
8
+ ---
9
+
10
+ ## Bug report for Cloudinary Ruby SDK
11
+ Before proceeding, please update to latest version and test if the issue persists
12
+
13
+ ## Describe the bug in a sentence or two.
14
+
15
+
16
+ ## Issue Type (Can be multiple)
17
+ [ ] Build - Can’t install or import the SDK
18
+ [ ] Performance - Performance issues
19
+ [ ] Behaviour - Functions aren’t working as expected (Such as generate URL)
20
+ [ ] Documentation - Inconsistency between the docs and behaviour
21
+ [ ] Other (Specify)
22
+
23
+ ## Steps to reproduce
24
+ … if applicable
25
+
26
+ ## Error screenshots or Stack Trace (if applicable)
27
+
28
+
29
+ ## Operating System
30
+ [ ] Linux
31
+ [ ] Windows
32
+ [ ] OSX
33
+ [ ] All
34
+
35
+ ## Environment and Libraries (fill in the version numbers)
36
+ Cloudinary Ruby SDK version - 0.0.0
37
+ Ruby Version - 0.0.0
38
+ Rails Version - 0.0.0
39
+ Other Libraries (Carrierwave, ActiveStorage, etc) - 0.0.0
40
+
41
+ ## Repository
42
+ If possible, please provide a link to a reproducible repository that showcases the problem
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: Feature request
3
+ about: Feature request for Cloudinary Ruby SDK
4
+ title: ''
5
+ labels: ''
6
+ assignees: const-cloudinary
7
+
8
+ ---
9
+
10
+ ## Feature request for Cloudinary Ruby SDK
11
+ …(If your feature is for other SDKs, please request them there)
12
+
13
+
14
+ ## Explain your use case
15
+ … (A high level explanation of why you need this feature)
16
+
17
+ ## Describe the problem you’re trying to solve
18
+ … (A more technical view of what you’d like to accomplish, and how this feature will help you achieve it)
19
+
20
+ ## Do you have a proposed solution?
21
+ … (yes, no? Please elaborate if needed)
@@ -1,4 +1,65 @@
1
1
 
2
+ 1.16.0 / 2020-06-29
3
+ ===================
4
+
5
+ New functionality and features
6
+ ------------------------------
7
+
8
+ * Add support for uploading `StringIO`
9
+
10
+ Other Changes
11
+ -------------
12
+
13
+ * Set default cache storage to `file` in `CarrierWave`
14
+ * Fix `normalize_expression` to ignore predefined variables
15
+ * Fix sample projects
16
+
17
+ 1.15.0 / 2020-06-11
18
+ ===================
19
+
20
+ New functionality and features
21
+ ------------------------------
22
+
23
+ * Add support for `accessibility_analysis` parameter
24
+
25
+ Other Changes
26
+ -------------
27
+ * Fix `download` function in `Cloudinary::CarrierWave`
28
+ * Fix handling of empty value in `if` parameter
29
+ * Fix consumption of configuration from environment variables
30
+
31
+ 1.14.0 / 2020-05-06
32
+ ===================
33
+
34
+ New functionality and features
35
+ ------------------------------
36
+
37
+ * Add support of global folder in ActiveStorage
38
+ * Add duration to conditions in video
39
+
40
+ Other Changes
41
+ -------------
42
+
43
+ * Fix `URI.unescape is obsolete` warning
44
+ * Fix lingering Rails 6 autoload warnings
45
+ * Fix Ruby 1.9 CI build
46
+ * Allow setting uploader timeout to `nil`
47
+ * Update link to CarrierWave integration
48
+ * Update issue templates
49
+
50
+ 1.13.2 / 2020-01-19
51
+ ===================
52
+
53
+ * Fix asset extension detection in active storage service `url` method
54
+
55
+ 1.13.1 / 2019-11-24
56
+ ===================
57
+
58
+ * Remove `test_files` from `gemspec`
59
+ * Remove redundant binary files from `active_storage` spec
60
+ * Fix `rspec` deprecation warnings in Rails 6
61
+ * Add test for uploading IO
62
+
2
63
  1.13.0 / 2019-11-14
3
64
  ===================
4
65
 
data/Rakefile CHANGED
@@ -1,55 +1,13 @@
1
1
  require 'bundler'
2
2
  require 'fileutils'
3
- require 'tmpdir'
4
- require 'rest_client'
5
- require 'json'
6
- require 'rubygems/package'
7
-
8
3
  require 'rspec/core/rake_task'
4
+
9
5
  RSpec::Core::RakeTask.new(:spec)
10
6
  task :default => :spec
11
7
 
12
8
  Bundler::GemHelper.install_tasks
13
9
 
14
- namespace :cloudinary do
15
- desc "Fetch the latest JavaScript library files and create the JavaScript index files"
16
- task :fetch_assets do
17
- index_files = %w[jquery.ui.widget.js jquery.iframe-transport.js jquery.fileupload.js jquery.cloudinary.js]
18
- processing_files = %w[canvas-to-blob.min.js load-image.all.min.js jquery.fileupload-process.js jquery.fileupload-image.js jquery.fileupload-validate.js]
19
- files = index_files + processing_files
20
-
21
- release = JSON(RestClient.get("https://api.github.com/repos/cloudinary/cloudinary_js/releases/latest"))
22
-
23
- FileUtils.rm_rf 'vendor/assets'
24
- html_folder = 'vendor/assets/html'
25
- FileUtils.mkdir_p html_folder
26
- js_folder = 'vendor/assets/javascripts/cloudinary'
27
- FileUtils.mkdir_p js_folder
28
-
29
- puts "Fetching cloudinary_js version #{release["tag_name"]}\n\n"
30
- sio = StringIO.new(RestClient.get(release["tarball_url"]).body)
31
- file =Zlib::GzipReader.new(sio)
32
- tar = Gem::Package::TarReader.new(file)
33
- tar.each_entry do |entry|
34
- name = File.basename(entry.full_name)
35
- if files.include? name
36
- js_full_name = File.join(js_folder, name)
37
- puts "Adding #{js_full_name}"
38
- File.write js_full_name, entry.read
39
- elsif name == 'cloudinary_cors.html'
40
- html_full_name = File.join(html_folder, name)
41
- puts "Adding #{html_full_name}"
42
- File.write html_full_name, entry.read
43
- end
44
- end
45
- puts "Creating 'index.js' and 'processing.js' files"
46
- File.open("vendor/assets/javascripts/cloudinary/index.js", "w") do |f|
47
- index_files.each { |name| f.puts "//= require ./#{name}" }
48
- end
49
- File.open("vendor/assets/javascripts/cloudinary/processing.js", "w") do |f|
50
- processing_files.each { |name| f.puts "//= require ./#{name}" }
51
- end
52
- end
10
+ path = File.expand_path(__dir__)
11
+ Dir.glob("#{path}/lib/tasks/**/*.rake").each { |f| import f }
53
12
 
54
- end
55
13
  task :build => "cloudinary:fetch_assets"
@@ -15,8 +15,7 @@ Gem::Specification.new do |s|
15
15
 
16
16
  s.rubyforge_project = "cloudinary"
17
17
 
18
- s.files = (`git ls-files`.split("\n") - `git ls-files samples`.split("\n")) + Dir.glob("vendor/assets/javascripts/*/*") + Dir.glob("vendor/assets/html/*")
19
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.files = (`git ls-files`.split("\n") - `git ls-files {test,spec,features,samples}/*`.split("\n")) + Dir.glob("vendor/assets/javascripts/*/*") + Dir.glob("vendor/assets/html/*")
20
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
20
  s.require_paths = ["lib"]
22
21
 
@@ -25,11 +24,25 @@ Gem::Specification.new do |s|
25
24
 
26
25
  s.add_development_dependency "actionpack"
27
26
  s.add_development_dependency "nokogiri"
28
- s.add_development_dependency "rake"
27
+
28
+ if RUBY_VERSION >= "2.2.0"
29
+ s.add_development_dependency "rake", ">= 13.0.1"
30
+ else
31
+ s.add_development_dependency "rake", "<= 12.2.1"
32
+ end
33
+
29
34
  s.add_development_dependency "sqlite3"
30
35
  s.add_development_dependency "rspec", '>=3.5'
31
36
  s.add_development_dependency "rails", "~>5.2" if RUBY_VERSION >= "2.2.2"
37
+
38
+ s.add_development_dependency "railties", "<= 4.2.7" if RUBY_VERSION <= "1.9.3"
32
39
  s.add_development_dependency "rspec-rails"
40
+
33
41
  s.add_development_dependency "rubyzip", "<=1.2.0" # support testing Ruby 1.9
34
- s.add_development_dependency "simplecov"
42
+
43
+ if RUBY_VERSION <= "2.4.0"
44
+ s.add_development_dependency "simplecov", "<= 0.17.1" # support testing Ruby 1.9
45
+ else
46
+ s.add_development_dependency "simplecov", "> 0.18.0"
47
+ end
35
48
  end
@@ -12,6 +12,15 @@ unless ActiveStorage::Blob.method_defined? :original_key
12
12
  end
13
13
  end
14
14
 
15
+ module CloudinaryHelper
16
+ alias cloudinary_url_internal_original cloudinary_url_internal
17
+
18
+ def cloudinary_url_internal(source, options = {})
19
+ source = ActiveStorage::Blob.service.public_id(source) if defined? ActiveStorage::Blob.service.public_id
20
+ cloudinary_url_internal_original(source, options)
21
+ end
22
+ end
23
+
15
24
  module ActiveStorage
16
25
  class Service::CloudinaryService < Service
17
26
  module Headers
@@ -22,7 +31,6 @@ module ActiveStorage
22
31
 
23
32
  def initialize(**options)
24
33
  @options = options
25
- @helper = ActionView::Base.new
26
34
  end
27
35
 
28
36
  def upload(key, io, filename: nil, checksum: nil, **options)
@@ -32,7 +40,7 @@ module ActiveStorage
32
40
  options = @options.merge(options)
33
41
  Cloudinary::Uploader.upload(
34
42
  io,
35
- public_id: public_id(key),
43
+ public_id: public_id_internal(key),
36
44
  resource_type: resource_type(io, key),
37
45
  context: {active_storage_key: key, checksum: checksum},
38
46
  extra_headers: extra_headers,
@@ -49,9 +57,10 @@ module ActiveStorage
49
57
  url = Cloudinary::Utils.cloudinary_url(
50
58
  public_id(key),
51
59
  resource_type: resource_type(nil, key),
52
- format: ext_for_content_type(content_type),
60
+ format: ext_for_file(filename, content_type),
53
61
  **@options.merge(options.symbolize_keys)
54
62
  )
63
+
55
64
  payload[:url] = url
56
65
 
57
66
  url
@@ -61,7 +70,7 @@ module ActiveStorage
61
70
  def url_for_direct_upload(key, **options)
62
71
  instrument :url, key: key do |payload|
63
72
  options = {:resource_type => resource_type(nil, key)}.merge(@options.merge(options.symbolize_keys))
64
- options[:public_id] = public_id(key)
73
+ options[:public_id] = public_id_internal(key)
65
74
  options[:context] = {active_storage_key: key}
66
75
  options.delete(:file)
67
76
  payload[:url] = api_uri("upload", options)
@@ -137,20 +146,41 @@ module ActiveStorage
137
146
 
138
147
  end
139
148
 
149
+ def public_id(key)
150
+ return key unless @options[:folder]
151
+
152
+ File.join(@options.fetch(:folder), public_id_internal(key))
153
+ end
154
+
140
155
  private
141
156
 
142
157
  def api_uri(action, options)
143
158
  base_url = Cloudinary::Utils.cloudinary_api_url(action, options)
144
159
  upload_params = Cloudinary::Uploader.build_upload_params(options)
145
160
 
146
- upload_params.reject! {|k, v| Cloudinary::Utils.safe_blank?(v)}
161
+ upload_params.reject! { |k, v| Cloudinary::Utils.safe_blank?(v) }
147
162
  unless options[:unsigned]
148
163
  upload_params = Cloudinary::Utils.sign_request(upload_params, options)
149
164
  end
150
165
  "#{base_url}?#{upload_params.to_query}"
151
166
  end
152
167
 
153
- def ext_for_content_type(content_type)
168
+ # Helper method for getting the filename extension.
169
+ #
170
+ # It does the best effort when original filename does not include extension, but we know the mime-type.
171
+ #
172
+ # @param [ActiveStorage::Filename] filename The original filename.
173
+ # @param [string] content_type The content type of the file.
174
+ #
175
+ # @return [string] The extension of the filename.
176
+ def ext_for_file(filename, content_type)
177
+ ext = filename.respond_to?(:extension_without_delimiter) ? filename.extension_without_delimiter : nil
178
+ return ext unless ext.blank?
179
+
180
+ # Raw files are not convertible, no extension guessing for them
181
+ return nil if content_type_to_resource_type(content_type).eql?('raw')
182
+
183
+ # Fallback when there is no extension.
154
184
  @formats ||= Hash.new do |h, key|
155
185
  ext = Rack::Mime::MIME_TYPES.invert[key]
156
186
  h[key] = ext.slice(1..-1) unless ext.nil?
@@ -158,14 +188,12 @@ module ActiveStorage
158
188
  @formats[content_type]
159
189
  end
160
190
 
161
- def public_id(key)
191
+ def public_id_internal(key)
162
192
  # TODO: Allow custom manipulation of key to obscure how we store in Cloudinary
163
193
  key
164
194
  end
165
195
 
166
- def resource_type(io, key = "")
167
- options = key.respond_to?(:attributes) ? key.attributes : {}
168
- content_type = options[:content_type] || (io.nil? ? '' : Marcel::MimeType.for(io))
196
+ def content_type_to_resource_type(content_type)
169
197
  type, subtype = content_type.split('/')
170
198
  case type
171
199
  when 'video', 'audio'
@@ -185,5 +213,11 @@ module ActiveStorage
185
213
  'image'
186
214
  end
187
215
  end
216
+
217
+ def resource_type(io, key = "")
218
+ options = key.respond_to?(:attributes) ? key.attributes : {}
219
+ content_type = options[:content_type] || (io.nil? ? '' : Marcel::MimeType.for(io))
220
+ content_type_to_resource_type(content_type)
221
+ end
188
222
  end
189
223
  end
@@ -64,19 +64,7 @@ module Cloudinary
64
64
  first_time = @@config.nil?
65
65
  @@config ||= OpenStruct.new((YAML.load(ERB.new(IO.read(config_dir.join("cloudinary.yml"))).result)[config_env] rescue {}))
66
66
 
67
- # Heroku support
68
- if first_time && ENV["CLOUDINARY_CLOUD_NAME"]
69
- set_config(
70
- "cloud_name" => ENV["CLOUDINARY_CLOUD_NAME"],
71
- "api_key" => ENV["CLOUDINARY_API_KEY"],
72
- "api_secret" => ENV["CLOUDINARY_API_SECRET"],
73
- "secure_distribution" => ENV["CLOUDINARY_SECURE_DISTRIBUTION"],
74
- "private_cdn" => ENV["CLOUDINARY_PRIVATE_CDN"].to_s == 'true',
75
- "secure" => ENV["CLOUDINARY_SECURE"].to_s == 'true'
76
- )
77
- elsif first_time && ENV["CLOUDINARY_URL"]
78
- config_from_url(ENV["CLOUDINARY_URL"])
79
- end
67
+ config_from_env if first_time
80
68
 
81
69
  set_config(new_config) if new_config
82
70
  yield(@@config) if block_given?
@@ -105,7 +93,7 @@ module Cloudinary
105
93
  if isNestedKey? key
106
94
  putNestedKey key, value
107
95
  else
108
- set_config(key => URI.decode(value))
96
+ set_config(key => Utils.smart_unescape(value))
109
97
  end
110
98
  end
111
99
  end
@@ -140,18 +128,34 @@ module Cloudinary
140
128
  end
141
129
 
142
130
  private
143
-
131
+
132
+ def self.config_from_env
133
+ # Heroku support
134
+ if ENV["CLOUDINARY_CLOUD_NAME"]
135
+ config_keys = ENV.keys.select! { |key| key.start_with? "CLOUDINARY_" }
136
+ config_keys -= ["CLOUDINARY_URL"] # ignore it when explicit options are passed
137
+ config_keys.each do |full_key|
138
+ conf_key = full_key["CLOUDINARY_".length..-1].downcase # convert "CLOUDINARY_CONFIG_NAME" to "config_name"
139
+ conf_val = ENV[full_key]
140
+ conf_val = conf_val == 'true' if %w[true false].include?(conf_val) # cast relevant boolean values
141
+ set_config(conf_key => conf_val)
142
+ end
143
+ elsif ENV["CLOUDINARY_URL"]
144
+ config_from_url(ENV["CLOUDINARY_URL"])
145
+ end
146
+ end
147
+
144
148
  def self.config_env
145
149
  return ENV["CLOUDINARY_ENV"] if ENV["CLOUDINARY_ENV"]
146
150
  return Rails.env if defined? Rails::env
147
151
  nil
148
152
  end
149
-
153
+
150
154
  def self.config_dir
151
- return Pathname.new(ENV["CLOUDINARY_CONFIG_DIR"]) if ENV["CLOUDINARY_CONFIG_DIR"]
155
+ return Pathname.new(ENV["CLOUDINARY_CONFIG_DIR"]) if ENV["CLOUDINARY_CONFIG_DIR"]
152
156
  self.app_root.join("config")
153
157
  end
154
-
158
+
155
159
  def self.set_config(new_config)
156
160
  new_config.each{|k,v| @@config.send(:"#{k}=", v) if !v.nil?}
157
161
  end
@@ -78,7 +78,7 @@ class Cloudinary::Api
78
78
  resource_type = options[:resource_type] || "image"
79
79
  type = options[:type] || "upload"
80
80
  uri = "resources/#{resource_type}/#{type}/#{public_id}"
81
- call_api(:get, uri,
81
+ call_api(:get, uri,
82
82
  only(options,
83
83
  :cinemagraph_analysis,
84
84
  :colors,
@@ -90,7 +90,8 @@ class Cloudinary::Api
90
90
  :pages,
91
91
  :phash,
92
92
  :quality_analysis,
93
- :derived_next_cursor
93
+ :derived_next_cursor,
94
+ :accessibility_analysis
94
95
  ), options)
95
96
  end
96
97