Sha256: 572820b052b3bdc7d37343f7e5ec7809639440e0511f412a6d37e7789dcb4be0

Contents?: true

Size: 1.98 KB

Versions: 2

Compression:

Stored size: 1.98 KB

Contents

# frozen_string_literal: true

module BulkLoader
  class Loader
    # +mapping+ is a Symbol or Proc. block's 1st argument mapped using mapping.
    # and your block's return value's key should be mapped value.
    def initialize(mapping, default: nil, &block)
      @mapping = mapping
      @is_mapping_proc = @mapping.is_a?(Proc)
      @default = default
      @is_default_proc = @default.is_a?(Proc)
      @block = block
    end

    def load(lazy_objs, *args)
      lazy_obj_of = lazy_objs.each_with_object({}) { |e, h| h[e.target] = e }

      mapping_of = get_mapping(lazy_objs)

      result_of = call_block(mapping_of, *args)

      lazy_objs.each(&:clear)

      set_result_to_lazy_objs(result_of, lazy_obj_of, mapping_of)

      fill_default_to_unloaded_obj(lazy_objs)
    end

    private

    def call_block(mapping_of, *args)
      if args.size < @block.arity - 1
        message = "block should take #{@block.arity} parameters, but given #{arity.size + 1}"
        raise ArgumentError, message
      end
      result_of = @block.call(mapping_of.keys, *args)
      raise 'block shuold return Hash' unless result_of.is_a?(Hash)
      result_of
    end

    def get_mapping(lazy_objs)
      mapping_of = {}
      targets = lazy_objs.map(&:target)
      targets.each do |target|
        mapped_target = @is_mapping_proc ? @mapping.call(target) : target.public_send(@mapping)
        mapping_of[mapped_target] = [] unless mapping_of[mapped_target]
        mapping_of[mapped_target].push(target)
      end
      mapping_of
    end

    def set_result_to_lazy_objs(result_of, lazy_obj_of, mapping_of)
      result_of.each do |mapped_target, value|
        next unless mapping_of[mapped_target]
        mapping_of[mapped_target].each do |target|
          lazy_obj_of[target]&.set(value)
        end
      end
    end

    def fill_default_to_unloaded_obj(lazy_objs)
      lazy_objs.each do |lazy_obj|
        lazy_obj.set(@is_default_proc ? @default.call : @default) unless lazy_obj.loaded?
      end
    end
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
bulk_loader-0.2.0 lib/bulk_loader/loader.rb
bulk_loader-0.1.0 lib/bulk_loader/loader.rb