class BatchLoader

Constants

IMPLEMENTED_INSTANCE_METHODS
LEFT_INSTANCE_METHODS
NoBatchError
REPLACABLE_INSTANCE_METHODS
VERSION

Public Class Methods

for(item) click to toggle source
# File lib/batch_loader.rb, line 17
def self.for(item)
  new(item: item)
end
new(item:, executor_proxy: nil) click to toggle source
# File lib/batch_loader.rb, line 21
def initialize(item:, executor_proxy: nil)
  @item = item
  @__executor_proxy = executor_proxy
end

Public Instance Methods

__sync() click to toggle source
# File lib/batch_loader.rb, line 50
def __sync
  return @loaded_value if @synced

  __ensure_batched
  @loaded_value = __executor_proxy.loaded_value(item: @item)

  if @cache
    @synced = true
  else
    __purge_cache
  end

  @loaded_value
end
batch(default_value: nil, cache: true, replace_methods: nil, key: nil, &batch_block) click to toggle source
# File lib/batch_loader.rb, line 26
def batch(default_value: nil, cache: true, replace_methods: nil, key: nil, &batch_block)
  @default_value = default_value
  @cache = cache
  @replace_methods = replace_methods.nil? ? cache : replace_methods
  @key = key
  @batch_block = batch_block

  __executor_proxy.add(item: @item)

  __singleton_class.class_eval { undef_method(:batch) }

  self
end
inspect() click to toggle source
# File lib/batch_loader.rb, line 46
def inspect
  "#<BatchLoader:0x#{(object_id << 1)}>"
end
respond_to?(method_name, include_private = false) click to toggle source
# File lib/batch_loader.rb, line 40
def respond_to?(method_name, include_private = false)
  return true if LEFT_INSTANCE_METHODS.include?(method_name)

  __loaded_value.respond_to?(method_name, include_private)
end

Private Instance Methods

__ensure_batched() click to toggle source
# File lib/batch_loader.rb, line 86
def __ensure_batched
  return if __executor_proxy.value_loaded?(item: @item)

  items = __executor_proxy.list_items
  loader = __loader
  args = {default_value: @default_value, cache: @cache, replace_methods: @replace_methods, key: @key}
  @batch_block.call(items, loader, args)
  items.each do |item|
    next if __executor_proxy.value_loaded?(item: item)
    loader.call(item, @default_value)
  end
  __executor_proxy.delete(items: items)
end
__executor_proxy() click to toggle source
# File lib/batch_loader.rb, line 137
def __executor_proxy
  @__executor_proxy ||= begin
    raise NoBatchError.new("Please provide a batch block first") unless @batch_block
    BatchLoader::ExecutorProxy.new(@default_value, @key, &@batch_block)
  end
end
__loaded_value() click to toggle source
# File lib/batch_loader.rb, line 67
def __loaded_value
  result = __sync!
  @cache ? @loaded_value : result
end
__loader() click to toggle source
# File lib/batch_loader.rb, line 100
def __loader
  mutex = Mutex.new
  -> (item, value = (no_value = true; nil), &block) do
    if no_value && !block
      raise ArgumentError, "Please pass a value or a block"
    elsif block && !no_value
      raise ArgumentError, "Please pass a value or a block, not both"
    end

    mutex.synchronize do
      next_value = block ? block.call(__executor_proxy.loaded_value(item: item)) : value
      __executor_proxy.load(item: item, value: next_value)
    end
  end
end
__purge_cache() click to toggle source
# File lib/batch_loader.rb, line 132
def __purge_cache
  __executor_proxy.unload_value(item: @item)
  __executor_proxy.add(item: @item)
end
__replace_with!(value) click to toggle source
# File lib/batch_loader.rb, line 120
def __replace_with!(value)
  __singleton_class.class_eval do
    (value.methods - LEFT_INSTANCE_METHODS).each do |method_name|
      define_method(method_name) do |*args, &block|
        value.public_send(method_name, *args, &block)
      end
    end
  end

  self
end
__singleton_class() click to toggle source
# File lib/batch_loader.rb, line 116
def __singleton_class
  class << self ; self ; end
end
__sync!() click to toggle source
# File lib/batch_loader.rb, line 76
def __sync!
  loaded_value = __sync

  if @replace_methods
    __replace_with!(loaded_value)
  else
    loaded_value
  end
end
method_missing(method_name, *args, &block) click to toggle source
# File lib/batch_loader.rb, line 72
def method_missing(method_name, *args, &block)
  __sync!.public_send(method_name, *args, &block)
end