lib/scorpion/stinger.rb
module Scorpion
# Utility methods for propagating a Scorpion to returned objects.
module Stinger
@wrappers ||= {}
def self.wrap( instance, stinger )
return instance unless instance
klass = @wrappers[instance.class] ||=
Class.new( instance.class ) do
def initialize( instance, stinger )
@__instance__ = instance
@__stinger__ = stinger
end
def respond_to?( *args )
@__instance__.respond_to?( *args )
end
private
def method_missing( *args, &block ) # rubocop:disable Style/MethodMissingSuper
@__stinger__.sting! @__instance__.__send__( *args, &block )
end
end
klass.new instance, stinger
end
# Sting an object so that it will be injected with the scorpion and use it
# to resolve all dependencies.
# @param [#scorpion] object to sting.
# @return [object] the object that was stung.
def sting!( object )
return object unless scorpion
if object
assign_scorpion object
assign_scorpion_to_enumerable object
end
object
end
private
def assign_scorpion( object )
return unless object.respond_to?( :scorpion=, true )
# Only set scorpion if it hasn't been set yet.
current_scorpion = object.send :scorpion
if current_scorpion
scorpion.logger.warn I18n.translate :mixed_scorpions, scope: [:scorpion, :warnings, :messages] if current_scorpion != scorpion # rubocop:disable Metrics/LineLength
else
object.send :scorpion=, scorpion
end
end
def assign_scorpion_to_enumerable( objects )
return unless objects.respond_to? :each
# Don't eager load relations that haven't been loaded yet.
return if objects.respond_to?( :loaded? ) && !objects.loaded?
objects.each { |v| sting! v }
end
end
end