module Shamu::Services::LazyAssociation

Lazily look up an associated resource

Constants

EXCLUDE_PATTERN
MUTEX

Public Class Methods

class_for( klass ) click to toggle source
# File lib/shamu/services/lazy_association.rb, line 9
def self.class_for( klass ) # rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity
  return klass.const_get( :Lazy_ ) if klass.const_defined?( :Lazy_ )

  MUTEX.synchronize do

    # Check again in case another thread defined it while waiting for the
    # mutex
    return klass.const_get( :Lazy_ ) if klass.const_defined?( :Lazy_ )

    lazy_class = Class.new( klass ) do
      # Remove all existing public methods so that they can be delegated
      # with #method_missing.
      klass.public_instance_methods.each do |method|
        next if EXCLUDE_PATTERN =~ method
        undef_method method
      end

      def initialize( id, &block )
        @id = id
        @block = block
      end

      # @!attribute
      # @return [Object] the primary key id of the association. Not delegated so
      #     it is safe to use and will not trigger an unnecessary fetch.
      attr_reader :id

      def __getobj__
        return @association if defined? @association

        @association = @block.call( @id ) if @block
      end

      def method_missing( method, *args, &block )
        if respond_to_missing?( method )
          __getobj__.public_send( method, *args, &block )
        else
          super
        end
      end

      def respond_to_missing?( method, include_private = false )
        __getobj__.respond_to?( method, include_private ) || super
      end

    end

    klass.const_set( :Lazy_, lazy_class )
    lazy_class
  end
end
new( id, &block ) click to toggle source
# File lib/shamu/services/lazy_association.rb, line 26
def initialize( id, &block )
  @id = id
  @block = block
end

Public Instance Methods

__getobj__() click to toggle source
# File lib/shamu/services/lazy_association.rb, line 36
def __getobj__
  return @association if defined? @association

  @association = @block.call( @id ) if @block
end
method_missing( method, *args, &block ) click to toggle source
Calls superclass method
# File lib/shamu/services/lazy_association.rb, line 42
def method_missing( method, *args, &block )
  if respond_to_missing?( method )
    __getobj__.public_send( method, *args, &block )
  else
    super
  end
end
respond_to_missing?( method, include_private = false ) click to toggle source
Calls superclass method
# File lib/shamu/services/lazy_association.rb, line 50
def respond_to_missing?( method, include_private = false )
  __getobj__.respond_to?( method, include_private ) || super
end