Skip to content

Commit 4f0b6ac

Browse files
Add support for ActiveStorage model service configuration
Fixes #558
1 parent d31de32 commit 4f0b6ac

5 files changed

Lines changed: 86 additions & 11 deletions

File tree

lib/active_storage/service/cloudinary_service.rb

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@ module CloudinaryHelper
1717
alias cloudinary_url_internal_original cloudinary_url_internal
1818

1919
def cloudinary_url_internal(source, options = {})
20-
if defined?(ActiveStorage::Blob.service.public_id) && options.fetch(:type, "").to_s != "fetch"
21-
source = ActiveStorage::Blob.service.public_id(source)
20+
service_instance, options = ActiveStorage::Service::CloudinaryService.fetch_service_instance_and_config(source, options)
21+
service_instance ||= ActiveStorage::Blob.service
22+
23+
if defined?(service_instance.public_id) && options.fetch(:type, "").to_s != "fetch"
24+
source = service_instance.public_id(source)
2225
end
26+
2327
cloudinary_url_internal_original(source, options)
2428
end
2529
end
@@ -190,6 +194,33 @@ def public_id(key, filename = nil, content_type = '')
190194
full_public_id_internal(public_id)
191195
end
192196

197+
def self.fetch_service_instance_and_config(source, options)
198+
return [nil, options] unless defined?(ActiveStorage::BlobKey) && source.is_a?(ActiveStorage::BlobKey) &&
199+
source.respond_to?(:attributes) && source.attributes.key?(:service_name)
200+
201+
service_name = source.attributes[:service_name]
202+
203+
begin
204+
service_instance = ActiveStorage::Blob.services.fetch(service_name.to_sym)
205+
206+
unless service_instance.instance_of?(ActiveStorage::Service::CloudinaryService)
207+
Rails.logger.error "Expected service instance #{service_instance.class.name} to be of type ActiveStorage::Service::CloudinaryService."
208+
return [nil, options]
209+
end
210+
211+
service_config = Rails.application.config.active_storage.service_configurations.fetch(service_name)
212+
options = service_config.merge(options)
213+
rescue NameError => e
214+
Rails.logger.error "Failed to retrieve the service instance for #{service_name}: #{e.message}"
215+
return [nil, options]
216+
rescue => e
217+
Rails.logger.error "An unexpected error occurred: #{e.message}"
218+
return [nil, options]
219+
end
220+
221+
[service_instance, options]
222+
end
223+
193224
private
194225

195226
def api_uri(action, options)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
11
local:
22
service: Disk
33
root: <%= Rails.root.join("storage") %>
4+
5+
cloudinary:
6+
service: Cloudinary
7+
type: authenticated
8+
tags:
9+
- ActiveStorageTestTag
10+
folder: active_storage_test_folder
11+
12+
cloudinary2:
13+
service: Cloudinary
14+
tags:
15+
- ActiveStorageTestTag2
16+
folder: active_storage_test_folder2
17+
cloud_name: test2

spec/active_storage/service/cloudinary_service_spec.rb

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
AS_TAG = "active_storage_" + SUFFIX
44
BASENAME = File.basename(TEST_IMG, '.*')
55

6-
CONFIGURATION_PATH = Pathname.new(File.expand_path("service/configurations.yml", __dir__))
6+
CONFIGURATION_PATH = Pathname.new(File.expand_path("dummy/config/storage.yml", __dir__))
77
SERVICE = ActiveStorage::Service.configure(:cloudinary, SERVICE_CONFIGURATIONS)
88

99
TEST_IMG_PATH = Pathname.new(TEST_IMG)
@@ -251,3 +251,39 @@
251251
end
252252
end
253253

254+
describe 'Active Storage CloudinaryHelper' do
255+
before :all do
256+
ActionView::Base.send :include, CloudinaryHelper
257+
end
258+
259+
let(:helper) {
260+
ActionView::Base.new(ActionView::LookupContext.new([]), {}, nil)
261+
}
262+
let(:custom_service_key) {
263+
ActiveStorage::BlobKey.new key: SecureRandom.base58(24), filename: BASENAME, service_name: 'cloudinary2'
264+
}
265+
let(:conf) {
266+
SERVICE_CONFIGURATIONS[:cloudinary2]
267+
}
268+
269+
it 'should respect custom service_name in cloudinary_url' do
270+
url = helper.cloudinary_url(custom_service_key)
271+
272+
expect(url).to include(conf[:folder])
273+
expect(url).to include(conf[:cloud_name])
274+
end
275+
276+
it 'should respect custom service_name in cl_image_path' do
277+
path = helper.cl_image_path(custom_service_key)
278+
279+
expect(path).to include(conf[:folder])
280+
expect(path).to include(conf[:cloud_name])
281+
end
282+
283+
it 'should respect custom service_name in cl_image_tag' do
284+
tag = helper.cl_image_tag(custom_service_key)
285+
286+
expect(tag).to include(conf[:folder])
287+
expect(tag).to include(conf[:cloud_name])
288+
end
289+
end

spec/active_storage/service/configurations.yml

Lines changed: 0 additions & 6 deletions
This file was deleted.

spec/active_storage/test_helper.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@
2727

2828
require "yaml"
2929
SERVICE_CONFIGURATIONS = begin
30-
erb = ERB.new(Pathname.new(File.expand_path("service/configurations.yml", __dir__)).read)
30+
erb = ERB.new(Pathname.new(File.expand_path("dummy/config/storage.yml", __dir__)).read)
3131
configuration = YAML.load(erb.result) || {}
3232
configuration.deep_symbolize_keys
3333
rescue Errno::ENOENT
34-
puts "Missing service configuration file in test/service/configurations.yml"
34+
puts "Missing service configuration file in dummy/config/storage.yml"
3535
{}
3636
end
3737

0 commit comments

Comments
 (0)