cloudinary 1.13.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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