lib/scorpion/dependency.rb
module Scorpion
# Dependency that can be injected into a {Scorpion::Object} by a {Scorpion}.
class Dependency
require "scorpion/dependency/captured_dependency"
require "scorpion/dependency/class_dependency"
require "scorpion/dependency/module_dependency"
require "scorpion/dependency/builder_dependency"
require "scorpion/dependency/argument_dependency"
# ============================================================================
# @!group Attributes
#
# @!attribute
# @return [Class,Module,Symbol] contract describing the desired behavior of the dependency.
attr_reader :contract
#
# @!endgroup Attributes
def initialize( contract )
@contract = contract
end
# @return [Boolean] if the dependency satisfies the required contract.
def satisfies?( contract )
satisfies_contract?( contract )
end
# Fetch an instance of the dependency.
# @param [Hunt] the hunting context.
# @return [Object] the hunted dependency.
def fetch( hunt )
fail "Not Implemented"
end
# Release the dependency, freeing up any long held resources.
def release
end
# Replicate the Dependency.
# @return [Dependency] a replication of the dependency.
def replicate
dup
end
def ==( other )
return unless other
self.class == other.class && contract == other.contract
end
alias_method :eql?, :==
def hash
self.class.hash ^ contract.hash
end
def inspect
result = "<#{ contract.inspect }"
result << ">"
result
end
private
# @return [Boolean] true if the pray satisfies the given contract.
def satisfies_contract?( contract )
if self.contract.is_a?(Symbol) || contract.is_a?(Symbol)
self.contract == contract
else
self.contract <= contract
end
end
class << self
# Define dependency based on the desired contract.
# @return [Dependency] the defined dependency.
def define( contract, options = {}, &builder )
if options.key?( :return )
Scorpion::Dependency::BuilderDependency.new( contract ) do
options[:return]
end
elsif with = options[ :with ]
Scorpion::Dependency::BuilderDependency.new( contract, with )
elsif block_given?
Scorpion::Dependency::BuilderDependency.new( contract, builder )
# Allow a Class/Module to define a #create method that will resolve
# and return an instance of itself. Do not automatically inherit the
# #create method so only consider it if the owner of the method is the
# contract itself.
elsif contract.respond_to?( :create ) && contract.singleton_methods( false ).include?( :create )
Scorpion::Dependency::BuilderDependency.new( contract ) do |hunt, *args, &block|
contract.create hunt, *args, &block
end
else
dependency_class( contract ).new( contract, &builder )
end
end
private
def dependency_class( contract, &builder )
return Scorpion::Dependency::ClassDependency if contract.is_a? Class
return Scorpion::Dependency::ModuleDependency if contract.is_a? Module
raise Scorpion::BuilderRequiredError
end
end
end
end