cloudinary 1.9.1 → 1.20.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.
- checksums.yaml +5 -5
- data/.github/ISSUE_TEMPLATE/bug_report.md +42 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
- data/.github/pull_request_template.md +24 -0
- data/.gitignore +7 -1
- data/.travis.yml +15 -8
- data/CHANGELOG.md +261 -0
- data/README.md +3 -0
- data/Rakefile +3 -45
- data/cloudinary.gemspec +27 -20
- data/lib/active_storage/blob_key.rb +20 -0
- data/lib/active_storage/service/cloudinary_service.rb +249 -0
- data/lib/cloudinary.rb +53 -63
- data/lib/cloudinary/account_api.rb +231 -0
- data/lib/cloudinary/account_config.rb +30 -0
- data/lib/cloudinary/api.rb +228 -71
- data/lib/cloudinary/auth_token.rb +10 -4
- data/lib/cloudinary/base_api.rb +79 -0
- data/lib/cloudinary/base_config.rb +70 -0
- data/lib/cloudinary/cache.rb +38 -0
- data/lib/cloudinary/cache/breakpoints_cache.rb +31 -0
- data/lib/cloudinary/cache/key_value_cache_adapter.rb +25 -0
- data/lib/cloudinary/cache/rails_cache_adapter.rb +34 -0
- data/lib/cloudinary/cache/storage/rails_cache_storage.rb +5 -0
- data/lib/cloudinary/carrier_wave.rb +4 -2
- data/lib/cloudinary/carrier_wave/remote.rb +3 -2
- data/lib/cloudinary/carrier_wave/storage.rb +2 -1
- data/lib/cloudinary/{controller.rb → cloudinary_controller.rb} +3 -5
- data/lib/cloudinary/config.rb +43 -0
- data/lib/cloudinary/helper.rb +77 -7
- data/lib/cloudinary/migrator.rb +3 -1
- data/lib/cloudinary/railtie.rb +7 -3
- data/lib/cloudinary/responsive.rb +111 -0
- data/lib/cloudinary/uploader.rb +67 -15
- data/lib/cloudinary/utils.rb +324 -54
- data/lib/cloudinary/version.rb +1 -1
- data/lib/cloudinary/video_helper.rb +96 -22
- data/lib/tasks/cloudinary/fetch_assets.rake +48 -0
- data/lib/tasks/{cloudinary.rake → cloudinary/sync_static.rake} +0 -0
- data/tools/allocate_test_cloud.sh +9 -0
- data/tools/get_test_cloud.sh +9 -0
- data/tools/update_version +220 -0
- data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +51 -13
- data/vendor/assets/javascripts/cloudinary/jquery.fileupload.js +24 -4
- data/vendor/assets/javascripts/cloudinary/jquery.ui.widget.js +741 -561
- data/vendor/assets/javascripts/cloudinary/load-image.all.min.js +1 -1
- metadata +92 -67
- data/spec/access_control_spec.rb +0 -99
- data/spec/api_spec.rb +0 -545
- data/spec/archive_spec.rb +0 -129
- data/spec/auth_token_spec.rb +0 -79
- data/spec/cloudinary_helper_spec.rb +0 -190
- data/spec/cloudinary_spec.rb +0 -32
- data/spec/data/sync_static/app/assets/javascripts/1.coffee +0 -1
- data/spec/data/sync_static/app/assets/javascripts/1.js +0 -1
- data/spec/data/sync_static/app/assets/stylesheets/1.css +0 -3
- data/spec/docx.docx +0 -0
- data/spec/favicon.ico +0 -0
- data/spec/logo.png +0 -0
- data/spec/rake_spec.rb +0 -160
- data/spec/sample_asset_file.tsv +0 -4
- data/spec/search_spec.rb +0 -109
- data/spec/spec_helper.rb +0 -245
- data/spec/storage_spec.rb +0 -44
- data/spec/streaminig_profiles_api_spec.rb +0 -74
- data/spec/support/helpers/temp_file_helpers.rb +0 -22
- data/spec/support/shared_contexts/rake.rb +0 -19
- data/spec/uploader_spec.rb +0 -363
- data/spec/utils_methods_spec.rb +0 -54
- data/spec/utils_spec.rb +0 -906
- data/spec/video_tag_spec.rb +0 -251
- data/spec/video_url_spec.rb +0 -164
data/cloudinary.gemspec
CHANGED
@@ -15,33 +15,40 @@ Gem::Specification.new do |s|
|
|
15
15
|
|
16
16
|
s.rubyforge_project = "cloudinary"
|
17
17
|
|
18
|
-
s.files =
|
19
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.files = `git ls-files`.split("\n").select { |f| !f.start_with?("test", "spec", "features", "samples") } + 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
|
|
23
22
|
s.add_dependency "aws_cf_signer"
|
24
|
-
s.add_development_dependency "rspec", '>=3.5'
|
25
|
-
s.add_development_dependency "rspec-rails"
|
26
|
-
s.add_development_dependency "rake"
|
27
23
|
|
28
|
-
if RUBY_VERSION
|
24
|
+
if RUBY_VERSION >= "2.0.0"
|
25
|
+
s.add_dependency "rest-client", ">= 2.0.0"
|
26
|
+
else
|
29
27
|
s.add_dependency "rest-client"
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
s.add_development_dependency "
|
37
|
-
s.add_development_dependency "simplecov"
|
38
|
-
s.add_development_dependency "nokogiri", "<1.7.0"
|
39
|
-
s.add_development_dependency "rubyzip", '<1.2.1'
|
28
|
+
end
|
29
|
+
|
30
|
+
s.add_development_dependency "actionpack"
|
31
|
+
s.add_development_dependency "nokogiri"
|
32
|
+
|
33
|
+
if RUBY_VERSION >= "2.2.0"
|
34
|
+
s.add_development_dependency "rake", ">= 13.0.1"
|
40
35
|
else
|
41
|
-
s.
|
42
|
-
s.add_dependency "rest-client", "<=1.6.8"
|
43
|
-
s.add_development_dependency "actionpack", "~>3.2.0"
|
44
|
-
s.add_development_dependency "nokogiri", "<1.6.0"
|
36
|
+
s.add_development_dependency "rake", "<= 12.2.1"
|
45
37
|
end
|
46
38
|
|
39
|
+
s.add_development_dependency "sqlite3"
|
40
|
+
s.add_development_dependency "rspec", '>=3.5'
|
41
|
+
s.add_development_dependency "rspec-retry"
|
42
|
+
s.add_development_dependency "rails", "~>5.2" if RUBY_VERSION >= "2.2.2"
|
43
|
+
|
44
|
+
s.add_development_dependency "railties", "<= 4.2.7" if RUBY_VERSION <= "1.9.3"
|
45
|
+
s.add_development_dependency "rspec-rails"
|
46
|
+
|
47
|
+
s.add_development_dependency "rubyzip"
|
48
|
+
|
49
|
+
if RUBY_VERSION <= "2.4.0"
|
50
|
+
s.add_development_dependency "simplecov", "<= 0.17.1" # support testing Ruby 1.9
|
51
|
+
else
|
52
|
+
s.add_development_dependency "simplecov", "> 0.18.0"
|
53
|
+
end
|
47
54
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Allow Blob attributes to be passed down to the service
|
2
|
+
# attributes includes
|
3
|
+
# - key - the string the BlobKey represents
|
4
|
+
# - content_type
|
5
|
+
# - filename
|
6
|
+
module ActiveStorage
|
7
|
+
class BlobKey < String
|
8
|
+
attr_reader :attributes
|
9
|
+
def initialize(attributes)
|
10
|
+
if attributes.is_a? Hash
|
11
|
+
attributes.symbolize_keys!
|
12
|
+
super(attributes[:key])
|
13
|
+
@attributes = attributes
|
14
|
+
else
|
15
|
+
super(attributes)
|
16
|
+
@attributes = {key: attributes} if attributes
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
require 'active_storage/blob_key'
|
2
|
+
require 'cloudinary/helper'
|
3
|
+
require 'net/http'
|
4
|
+
|
5
|
+
unless ActiveStorage::Blob.method_defined? :original_key
|
6
|
+
class ActiveStorage::Blob
|
7
|
+
alias_method :original_key, :key
|
8
|
+
|
9
|
+
def key
|
10
|
+
original_key
|
11
|
+
ActiveStorage::BlobKey.new(@attributes.as_json)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module CloudinaryHelper
|
17
|
+
alias cloudinary_url_internal_original cloudinary_url_internal
|
18
|
+
|
19
|
+
def cloudinary_url_internal(source, options = {})
|
20
|
+
source = ActiveStorage::Blob.service.public_id(source) if defined? ActiveStorage::Blob.service.public_id
|
21
|
+
cloudinary_url_internal_original(source, options)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module ActiveStorage
|
26
|
+
class Service::CloudinaryService < Service
|
27
|
+
module Headers
|
28
|
+
CONTENT_TYPE = "Content-Type".freeze
|
29
|
+
CONTENT_MD5 = "Content-MD5".freeze
|
30
|
+
end
|
31
|
+
attr_reader :upload_options
|
32
|
+
|
33
|
+
def initialize(**options)
|
34
|
+
@options = options
|
35
|
+
end
|
36
|
+
|
37
|
+
def upload(key, io, filename: nil, checksum: nil, **options)
|
38
|
+
instrument :upload, key: key, checksum: checksum do
|
39
|
+
begin
|
40
|
+
extra_headers = checksum.nil? ? {} : {Headers::CONTENT_MD5 => checksum}
|
41
|
+
options = @options.merge(options)
|
42
|
+
Cloudinary::Uploader.upload(
|
43
|
+
io,
|
44
|
+
public_id: public_id_internal(key),
|
45
|
+
resource_type: resource_type(io, key),
|
46
|
+
context: {active_storage_key: key, checksum: checksum},
|
47
|
+
extra_headers: extra_headers,
|
48
|
+
**options
|
49
|
+
)
|
50
|
+
rescue CloudinaryException => e
|
51
|
+
raise ActiveStorage::IntegrityError, e.message, e.backtrace
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def url(key, filename: nil, content_type: '', **options)
|
57
|
+
instrument :url, key: key do |payload|
|
58
|
+
url = Cloudinary::Utils.cloudinary_url(
|
59
|
+
public_id(key),
|
60
|
+
resource_type: resource_type(nil, key),
|
61
|
+
format: ext_for_file(key, filename, content_type),
|
62
|
+
**@options.merge(options.symbolize_keys)
|
63
|
+
)
|
64
|
+
|
65
|
+
payload[:url] = url
|
66
|
+
|
67
|
+
url
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def url_for_direct_upload(key, **options)
|
72
|
+
instrument :url, key: key do |payload|
|
73
|
+
options = {:resource_type => resource_type(nil, key)}.merge(@options.merge(options.symbolize_keys))
|
74
|
+
options[:public_id] = public_id_internal(key)
|
75
|
+
# Provide file format for raw files, since js client does not include original file name.
|
76
|
+
#
|
77
|
+
# When the file is uploaded from the server, the request includes original filename. That allows Cloudinary
|
78
|
+
# to identify file extension and append it to the public id of the file (raw files include file extension
|
79
|
+
# in their public id, opposed to transformable assets (images/video) that use only basename). When uploading
|
80
|
+
# through direct upload (client side js), filename is missing, and that leads to inconsistent/broken URLs.
|
81
|
+
# To avoid that, we explicitly pass file format in options.
|
82
|
+
options[:format] = ext_for_file(key) if options[:resource_type] == "raw"
|
83
|
+
options[:context] = {active_storage_key: key}
|
84
|
+
options.delete(:file)
|
85
|
+
payload[:url] = api_uri("upload", options)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def headers_for_direct_upload(key, content_type:, checksum:, **)
|
90
|
+
{
|
91
|
+
Headers::CONTENT_TYPE => content_type,
|
92
|
+
Headers::CONTENT_MD5 => checksum,
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
def delete(key)
|
97
|
+
instrument :delete, key: key do
|
98
|
+
options = {
|
99
|
+
resource_type: resource_type(nil, key),
|
100
|
+
type: @options[:type]
|
101
|
+
}.compact
|
102
|
+
|
103
|
+
Cloudinary::Uploader.destroy public_id(key), **options
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def delete_prefixed(prefix)
|
108
|
+
# This method is used by ActiveStorage to delete derived resources after the main resource was deleted.
|
109
|
+
# In Cloudinary, the derived resources are deleted automatically when the main resource is deleted.
|
110
|
+
end
|
111
|
+
|
112
|
+
def exist?(key)
|
113
|
+
instrument :exist, key: key do |payload|
|
114
|
+
begin
|
115
|
+
options = {
|
116
|
+
resource_type: resource_type(nil, key),
|
117
|
+
type: @options[:type]
|
118
|
+
}.compact
|
119
|
+
|
120
|
+
Cloudinary::Api.resource public_id(key), **options
|
121
|
+
true
|
122
|
+
rescue Cloudinary::Api::NotFound => e
|
123
|
+
false
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def download(key, &block)
|
129
|
+
uri = URI(url(key))
|
130
|
+
if block_given?
|
131
|
+
instrument :streaming_download, key: key do
|
132
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
133
|
+
request = Net::HTTP::Get.new uri
|
134
|
+
http.request request do |response|
|
135
|
+
response.read_body &block
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
else
|
140
|
+
instrument :download, key: key do
|
141
|
+
res = Net::HTTP::get_response(uri)
|
142
|
+
res.body
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Return the partial content in the byte +range+ of the file at the +key+.
|
148
|
+
def download_chunk(key, range)
|
149
|
+
url = Cloudinary::Utils.unsigned_download_url(public_id(key), resource_type: resource_type(nil, key))
|
150
|
+
uri = URI(url)
|
151
|
+
instrument :download, key: key do
|
152
|
+
req = Net::HTTP::Get.new(uri)
|
153
|
+
range_end = case
|
154
|
+
when range.end.nil? then ''
|
155
|
+
when range.exclude_end? then range.end - 1
|
156
|
+
else range.end
|
157
|
+
end
|
158
|
+
req['range'] = "bytes=#{[range.begin, range_end].join('-')}"
|
159
|
+
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
160
|
+
http.request(req)
|
161
|
+
end
|
162
|
+
res.body.force_encoding(Encoding::BINARY)
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
def public_id(key)
|
168
|
+
return key unless @options[:folder]
|
169
|
+
|
170
|
+
File.join(@options.fetch(:folder), public_id_internal(key))
|
171
|
+
end
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
def api_uri(action, options)
|
176
|
+
base_url = Cloudinary::Utils.cloudinary_api_url(action, options)
|
177
|
+
upload_params = Cloudinary::Uploader.build_upload_params(options)
|
178
|
+
|
179
|
+
upload_params.reject! { |k, v| Cloudinary::Utils.safe_blank?(v) }
|
180
|
+
unless options[:unsigned]
|
181
|
+
upload_params = Cloudinary::Utils.sign_request(upload_params, options)
|
182
|
+
end
|
183
|
+
"#{base_url}?#{upload_params.to_query}"
|
184
|
+
end
|
185
|
+
|
186
|
+
# Helper method for getting the filename extension.
|
187
|
+
#
|
188
|
+
# It does the best effort when original filename does not include extension, but we know the mime-type.
|
189
|
+
#
|
190
|
+
# @param [ActiveStorage::BlobKey] key The blob key with attributes.
|
191
|
+
# @param [ActiveStorage::Filename] filename The original filename.
|
192
|
+
# @param [string] content_type The content type of the file.
|
193
|
+
#
|
194
|
+
# @return [string] The extension of the filename.
|
195
|
+
def ext_for_file(key, filename = nil, content_type = nil)
|
196
|
+
if filename.blank?
|
197
|
+
options = key.respond_to?(:attributes) ? key.attributes : {}
|
198
|
+
filename = ActiveStorage::Filename.new(options[:filename]) if options.has_key?(:filename)
|
199
|
+
end
|
200
|
+
ext = filename.respond_to?(:extension_without_delimiter) ? filename.extension_without_delimiter : nil
|
201
|
+
|
202
|
+
return ext unless ext.blank?
|
203
|
+
|
204
|
+
# Raw files are not convertible, no extension guessing for them
|
205
|
+
return nil if content_type_to_resource_type(content_type).eql?('raw')
|
206
|
+
|
207
|
+
# Fallback when there is no extension.
|
208
|
+
@formats ||= Hash.new do |h, key|
|
209
|
+
ext = Rack::Mime::MIME_TYPES.invert[key]
|
210
|
+
h[key] = ext.slice(1..-1) unless ext.nil?
|
211
|
+
end
|
212
|
+
@formats[content_type]
|
213
|
+
end
|
214
|
+
|
215
|
+
def public_id_internal(key)
|
216
|
+
# TODO: Allow custom manipulation of key to obscure how we store in Cloudinary
|
217
|
+
key
|
218
|
+
end
|
219
|
+
|
220
|
+
def content_type_to_resource_type(content_type)
|
221
|
+
return 'image' if content_type.nil?
|
222
|
+
|
223
|
+
type, subtype = content_type.split('/')
|
224
|
+
case type
|
225
|
+
when 'video', 'audio'
|
226
|
+
'video'
|
227
|
+
when 'text'
|
228
|
+
'raw'
|
229
|
+
when 'application'
|
230
|
+
case subtype
|
231
|
+
when 'pdf', 'postscript'
|
232
|
+
'image'
|
233
|
+
when 'vnd.apple.mpegurl', 'x-mpegurl', 'mpegurl' # m3u8
|
234
|
+
'video'
|
235
|
+
else
|
236
|
+
'raw'
|
237
|
+
end
|
238
|
+
else
|
239
|
+
'image'
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def resource_type(io, key = "")
|
244
|
+
options = key.respond_to?(:attributes) ? key.attributes : {}
|
245
|
+
content_type = options[:content_type] || (io.nil? ? '' : Marcel::MimeType.for(io))
|
246
|
+
content_type_to_resource_type(content_type)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
data/lib/cloudinary.rb
CHANGED
@@ -16,7 +16,12 @@ require "cloudinary/missing"
|
|
16
16
|
module Cloudinary
|
17
17
|
autoload :Utils, 'cloudinary/utils'
|
18
18
|
autoload :Uploader, 'cloudinary/uploader'
|
19
|
+
autoload :BaseConfig, "cloudinary/base_config"
|
20
|
+
autoload :Config, "cloudinary/config"
|
21
|
+
autoload :AccountConfig, "cloudinary/account_config"
|
22
|
+
autoload :BaseApi, "cloudinary/base_api"
|
19
23
|
autoload :Api, "cloudinary/api"
|
24
|
+
autoload :AccountApi, "cloudinary/account_api"
|
20
25
|
autoload :Downloader, "cloudinary/downloader"
|
21
26
|
autoload :Blob, "cloudinary/blob"
|
22
27
|
autoload :PreloadedFile, "cloudinary/preloaded_file"
|
@@ -29,8 +34,8 @@ module Cloudinary
|
|
29
34
|
OLD_AKAMAI_SHARED_CDN = "cloudinary-a.akamaihd.net"
|
30
35
|
SHARED_CDN = AKAMAI_SHARED_CDN
|
31
36
|
|
32
|
-
USER_AGENT = "CloudinaryRuby
|
33
|
-
@@user_platform = ""
|
37
|
+
USER_AGENT = "CloudinaryRuby/#{VERSION} (Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL})"
|
38
|
+
@@user_platform = defined?(Rails.version) ? "Rails/#{Rails.version}" : ""
|
34
39
|
|
35
40
|
# Add platform information to the USER_AGENT header
|
36
41
|
# This is intended for platform information and not individual applications!
|
@@ -44,7 +49,7 @@ module Cloudinary
|
|
44
49
|
|
45
50
|
def self.USER_AGENT
|
46
51
|
if @@user_platform.empty?
|
47
|
-
|
52
|
+
USER_AGENT
|
48
53
|
else
|
49
54
|
"#{@@user_platform} #{USER_AGENT}"
|
50
55
|
end
|
@@ -58,71 +63,42 @@ module Cloudinary
|
|
58
63
|
"ept" => "eps"
|
59
64
|
}
|
60
65
|
|
61
|
-
|
62
|
-
|
66
|
+
# Cloudinary config
|
67
|
+
#
|
68
|
+
# @param [Hash] new_config If +new_config+ is passed, Config will be updated with it
|
69
|
+
# @yieldparam [OpenStruct] Config can be updated in the block
|
70
|
+
#
|
71
|
+
# @return [OpenStruct]
|
63
72
|
def self.config(new_config=nil)
|
64
|
-
|
65
|
-
@@config ||= OpenStruct.new((YAML.load(ERB.new(IO.read(config_dir.join("cloudinary.yml"))).result)[config_env] rescue {}))
|
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
|
73
|
+
@@config ||= make_new_config(Config)
|
80
74
|
|
81
|
-
|
82
|
-
yield
|
75
|
+
@@config.update(new_config) if new_config
|
76
|
+
yield @@config if block_given?
|
83
77
|
|
84
78
|
@@config
|
85
79
|
end
|
86
80
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
"secure_distribution" => uri.path[1..-1]
|
96
|
-
)
|
97
|
-
uri.query.to_s.split("&").each do
|
98
|
-
|param|
|
99
|
-
key, value = param.split("=")
|
100
|
-
if isNestedKey? key
|
101
|
-
putNestedKey key, value
|
102
|
-
else
|
103
|
-
set_config(key => URI.decode(value))
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
81
|
+
# Cloudinary account config
|
82
|
+
#
|
83
|
+
# @param [Hash] new_config If +new_config+ is passed, Account Config will be updated with it
|
84
|
+
# @yieldparam [OpenStruct] Account config can be updated in the block
|
85
|
+
#
|
86
|
+
# @return [OpenStruct]
|
87
|
+
def self.account_config(new_config=nil)
|
88
|
+
@@account_config ||= make_new_config(AccountConfig)
|
107
89
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
chain.each do |innerKey|
|
113
|
-
inner = outer[innerKey]
|
114
|
-
if inner.nil?
|
115
|
-
inner = OpenStruct.new
|
116
|
-
outer[innerKey] = inner
|
117
|
-
end
|
118
|
-
outer = inner
|
119
|
-
end
|
120
|
-
outer[lastKey] = value
|
90
|
+
@@account_config.update(new_config) if new_config
|
91
|
+
yield @@account_config if block_given?
|
92
|
+
|
93
|
+
@@account_config
|
121
94
|
end
|
122
95
|
|
96
|
+
def self.config_from_url(url)
|
97
|
+
config.load_from_url(url)
|
98
|
+
end
|
123
99
|
|
124
|
-
def self.
|
125
|
-
|
100
|
+
def self.config_from_account_url(url)
|
101
|
+
account_config.load_from_url(url)
|
126
102
|
end
|
127
103
|
|
128
104
|
def self.app_root
|
@@ -135,25 +111,39 @@ module Cloudinary
|
|
135
111
|
end
|
136
112
|
|
137
113
|
private
|
138
|
-
|
114
|
+
|
139
115
|
def self.config_env
|
140
116
|
return ENV["CLOUDINARY_ENV"] if ENV["CLOUDINARY_ENV"]
|
141
117
|
return Rails.env if defined? Rails::env
|
142
118
|
nil
|
143
119
|
end
|
144
|
-
|
120
|
+
|
145
121
|
def self.config_dir
|
146
|
-
return Pathname.new(ENV["CLOUDINARY_CONFIG_DIR"]) if ENV["CLOUDINARY_CONFIG_DIR"]
|
122
|
+
return Pathname.new(ENV["CLOUDINARY_CONFIG_DIR"]) if ENV["CLOUDINARY_CONFIG_DIR"]
|
147
123
|
self.app_root.join("config")
|
148
124
|
end
|
149
|
-
|
125
|
+
|
150
126
|
def self.set_config(new_config)
|
151
127
|
new_config.each{|k,v| @@config.send(:"#{k}=", v) if !v.nil?}
|
152
128
|
end
|
129
|
+
|
130
|
+
# Builds config from yaml file, extends it with specific module and loads configuration from environment variable
|
131
|
+
#
|
132
|
+
# @param [Module] config_module Config is extended with this module after being built
|
133
|
+
#
|
134
|
+
# @return [OpenStruct]
|
135
|
+
def self.make_new_config(config_module)
|
136
|
+
OpenStruct.new((YAML.load(ERB.new(IO.read(config_dir.join("cloudinary.yml"))).result)[config_env] rescue {})).tap do |config|
|
137
|
+
config.extend(config_module)
|
138
|
+
config.load_config_from_env
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
private_class_method :make_new_config
|
153
143
|
end
|
154
144
|
# Prevent require loop if included after Rails is already initialized.
|
155
145
|
require "cloudinary/helper" if defined?(::ActionView::Base)
|
156
|
-
require "cloudinary/
|
146
|
+
require "cloudinary/cloudinary_controller" if defined?(::ActionController::Base)
|
157
147
|
require "cloudinary/railtie" if defined?(Rails) && defined?(Rails::Railtie)
|
158
148
|
require "cloudinary/engine" if defined?(Rails) && defined?(Rails::Engine)
|
159
149
|
|