1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Clarify how a service can build other composed services

* Service.build takes the literal YAML config hash for the service and a
  reference to the Configurator that's doing the building.
* Services that compose additional services can use the Configurator to
  look them up and build them by name. See MirrorService for an example.

References #23
This commit is contained in:
Jeremy Daer 2017-07-09 04:23:21 -07:00
parent 1a17cfb9d9
commit 4d292fc0e7
No known key found for this signature in database
GPG key ID: AB8F6399D5C60664
5 changed files with 39 additions and 38 deletions

View file

@ -32,15 +32,24 @@
class ActiveStorage::Service
class ActiveStorage::IntegrityError < StandardError; end
extend ActiveSupport::Autoload
autoload :Configurator
# Configure an Active Storage service by name from a set of configurations,
# typically loaded from a YAML file. The Active Storage engine uses this
# to set the global Active Storage service when the app boots.
def self.configure(service_name, configurations)
require 'active_storage/service/configurator'
Configurator.new(service_name, configurations).build
Configurator.build(service_name, configurations)
end
# Override in subclasses that stitch together multiple services and hence
# need to do additional lookups from configurations. See MirrorService.
def self.build(service_config, all_configurations) #:nodoc:
new(service_config)
# need to build additional services using the configurator.
#
# Passes the configurator and all of the service's config as keyword args.
#
# See MirrorService for an example.
def self.build(configurator:, service: nil, **service_config) #:nodoc:
new(**service_config)
end
def upload(key, io, checksum: nil)

View file

@ -1,31 +1,28 @@
class ActiveStorage::Service::Configurator #:nodoc:
def initialize(service_name, configurations)
@service_name, @configurations = service_name.to_sym, configurations.symbolize_keys
attr_reader :configurations
def self.build(service_name, configurations)
new(configurations).build(service_name)
end
def build
service_class.build(service_config.except(:service), @configurations)
def initialize(configurations)
@configurations = configurations.symbolize_keys
end
def build(service_name)
config = config_for(service_name.to_sym)
resolve(config.fetch(:service)).build(**config, configurator: self)
end
private
def service_class
resolve service_class_name
end
def service_class_name
service_config.fetch :service do
raise "Missing Active Storage `service: …` configuration for #{service_config.inspect}"
def config_for(name)
configurations.fetch name do
raise "Missing configuration for the #{name.inspect} Active Storage service. Configurations available for #{configurations.keys.inspect}"
end
end
def service_config
@configurations.fetch @service_name do
raise "Missing configuration for the #{@service_name.inspect} Active Storage service. Configurations available for #{@configurations.keys.inspect}"
end
end
def resolve(service_class_name)
require "active_storage/service/#{service_class_name.to_s.downcase}_service"
ActiveStorage::Service.const_get(:"#{service_class_name}Service")
def resolve(class_name)
require "active_storage/service/#{class_name.to_s.downcase}_service"
ActiveStorage::Service.const_get(:"#{class_name}Service")
end
end

View file

@ -5,15 +5,11 @@ class ActiveStorage::Service::MirrorService < ActiveStorage::Service
delegate :download, :exist?, :url, to: :primary
# Stitch together from named configuration.
def self.build(service_config, all_configurations) #:nodoc:
primary = ActiveStorage::Service.configure(service_config.fetch(:primary), all_configurations)
mirrors = service_config.fetch(:mirrors).collect do |service_name|
ActiveStorage::Service.configure(service_name.to_sym, all_configurations)
end
new primary: primary, mirrors: mirrors
# Stitch together from named services.
def self.build(primary:, mirrors:, configurator:, **options) #:nodoc:
new \
primary: configurator.build(primary),
mirrors: mirrors.collect { |name| configurator.build name }
end
def initialize(primary:, mirrors:)

View file

@ -2,7 +2,7 @@ require "tmpdir"
require "service/shared_service_tests"
class ActiveStorage::Service::DiskServiceTest < ActiveSupport::TestCase
SERVICE = ActiveStorage::Service.configure(:test, test: { service: "Disk", root: File.join(Dir.tmpdir, "active_storage") })
SERVICE = ActiveStorage::Service::DiskService.new(root: File.join(Dir.tmpdir, "active_storage"))
include ActiveStorage::Service::SharedServiceTests
end

View file

@ -5,9 +5,8 @@ require "active_support/testing/autorun"
require "byebug"
require "active_storage"
require "active_storage/service"
ActiveStorage::Blob.service = ActiveStorage::Service.configure(:test, test: { service: 'Disk', root: File.join(Dir.tmpdir, "active_storage") })
require "active_storage/service/disk_service"
ActiveStorage::Blob.service = ActiveStorage::Service::DiskService.new(root: File.join(Dir.tmpdir, "active_storage"))
require "active_storage/verified_key_with_expiration"
ActiveStorage::VerifiedKeyWithExpiration.verifier = ActiveSupport::MessageVerifier.new("Testing")