lib/milan/registry.rb
require 'dry/container'
require 'dry/auto_inject'
require 'hanami/utils/string'
module Milan
# Prefer an insulation layer instead of direct extension of an object
class Container
include Dry::Container::Mixin
end
private_constant :Container
# A container module for registrations related to Milan. The idea is to provide a clear location for both defining interactions
# as well as the means for doing dependency injection. I would love for more explicit interface definitions in the registry
# but for now I'll settle with a consolidated location for that information.
module Registry
# :reek:TooManyStatements: { exclude: [ 'Milan::Registry#self.registration_container' ] }
#
# @todo I don't want to use the ||= as that is not a good thread safe pattern. Until I introduce an initializer (or use this in a
# multi-threaded instance) this is adequate.
def self.registration_container
@registration_container ||= Container.new.tap do |container|
container.register(:form_builder) { Milan::FormBuilder.method(:new) }
container.register(:form_instance_builder) { Milan::FormInstance.method(:new) }
container.register(:predicate_aggregate_builder) { Milan::PredicateAggregator.method(:new) }
container.register(:predicate_builder) { Milan::Predicate.method(:new) }
container.register(:predicate_set_builder) { Milan::PredicateSet.method(:new) }
container.register(:predicate_translator) { Milan::TranslationAssistant.method(:for_predicate) }
container.register(
:to_method_name,
->(input) { Hanami::Utils::String.new(input.to_s.gsub(/\W+/, '_').sub(/\A_/, '')).underscore.chomp('_') }
)
end
end
private_class_method :registration_container
def self.inject(*names, type: :hash)
Dry::Injection.new(registration_container, type: type)[*names]
end
def self.resolve(name, *args, &block)
resolver_for(name).call(*args, &block)
end
def self.resolver_for(name)
registration_container.resolve(name)
end
end
end
# These are declared after the Milan::Registry module is defined. If the requires occur before the module definition the following error
# occurs:
# ```console
# ./milan/lib/milan/predicate.rb:18:in `<class:Predicate>': uninitialized constant Milan::Registry (NameError)
# ```
require 'milan/form_builder'
require 'milan/form_instance'
require 'milan/predicate_aggregator'
require 'milan/predicate_set'
require 'milan/predicate'
require 'milan/translation_assistant'