phallguy/scorpion

View on GitHub
lib/scorpion/stinger.rb

Summary

Maintainability
A
25 mins
Test Coverage
D
65%
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