class PIM::Services::Loader

Public Class Methods

is_cached?(object) click to toggle source
# File services.rb, line 388
def self.is_cached? object
  return (object.respond_to?(:cached?) and object.cached?)
end
load(data_module, request, *loaders) click to toggle source

Default load method execute a request on the specified data module

# File services.rb, line 328
def self.load data_module, request, *loaders

  return request.empty_result if loaders.empty?

  # Check if loaders can handle the request
  result = load_from_next_loader(data_module, request, *loaders)

  # If no result was returned and the request has a redirect block, execute that block
  if result.nil? and request.redirect?
    result = request.redirect(data_module, *loaders)
  end

  # Depending on the request's return_type, we need to update the result
  if request.return_type == Hash

    # If result is an Array and no keys were requested,
    # it denotes the list of the actual keys to use.
    # In this case, create a new request with those keys
    # and try again!
    if PIM.is_array?(result) and not result.empty? and request.keys.empty?
      request = request.copy(keys: result)
      result = load(data_module, request, *loaders)
    end

  elsif request.return_type == Array

    # If result is a Hash, we expect the values of each Hash entry to be Arrays,
    # so simply combine all values
    if PIM.is_hash?(result)
      result = result.values.flatten.compact.uniq
    end

  end

  return result || request.empty_result
end
load_from_next_loader(data_module, request, *loaders) click to toggle source

Helper method to return the result using the next loader in the list

# File services.rb, line 367
def self.load_from_next_loader data_module, request, *loaders
  loader = loaders.shift
  return loader.load(data_module, request, *loaders) unless loader.nil?
end
set_cached(object, cached = true) click to toggle source
# File services.rb, line 372
def self.set_cached object, cached = true
  if cached
    class << object
      def cached?
        true
      end
    end
  else
    class << object
      def cached?
        false
      end
    end
  end
end

Public Instance Methods

close() click to toggle source

Implement in subclass

# File services.rb, line 500
def close
end
enabled?() click to toggle source

Override in subclass

# File services.rb, line 463
def enabled?
  true
end
get(data_module, request) click to toggle source

Implement in subclass

# File services.rb, line 489
def get data_module, request
  return nil
end
get_base_key(request) click to toggle source

Helper method to create the base key for flat key-value loaders

# File services.rb, line 614
def get_base_key request
  base_keys = get_base_keys(request)
  return base_keys.join(':')
end
get_base_keys(request) click to toggle source

Helper method to create the base keys for structured key-value loaders

# File services.rb, line 606
def get_base_keys request
  base_keys = [ request.request_name ]
  base_keys += request.parent unless request.parent.nil?
  return base_keys
end
get_data_model_definitions_file(data_module, *file_extensions) click to toggle source

Helper method to retrieve the data-model definitions file from a data_module

# File services.rb, line 515
def get_data_model_definitions_file data_module, *file_extensions
  if PIM.has_module?(data_module)
    data_module.get_data_model_definitions_file(*file_extensions)
  else
    nil
  end
end
get_from_repository(repository, request, cached: false, return_nil: false) click to toggle source

Helper method for structured key-value repositories to get the result from a “repository”.

# File services.rb, line 526
def get_from_repository repository, request, cached: false, return_nil: false

  return nil if repository.nil? or repository.empty? or request.nil?

  # Get the base repository, if it exists
  base_keys = get_base_keys(request)
  base_keys.each do |base_key|
    repository = repository[base_key]
    return nil if repository.nil? or repository.empty?
  end

  # If no keys were specified in the request,
  # return the cached list of ALL keys, if it exists
  if request.keys.empty?

    result = repository[nil]

  elsif request.return_type == Hash

    result = {}
    request.keys.each do |key|

      # Only add 'nil' results if explicitly allowed.
      # E.g. for a caching loader, only return nil if previously added by 'put'.
      # Otherwise we would not check the next loaders!
      next unless (return_nil or repository.include?(key))

      result[key] = repository[key]

    end

  end

  # Mark the result as "cached", if necessary
  Loader.set_cached(result, cached)

  return result
end
get_redirect(data_module, request, *loaders) click to toggle source

Default implementation to get redirected result from next loader

# File services.rb, line 483
def get_redirect data_module, request, *loaders
  return load_from_next_loader(data_module, request, *loaders)
end
get_service_name(data_module) click to toggle source

Helper method to retrieve the service-name from a data_module

# File services.rb, line 505
def get_service_name data_module
  if PIM.has_module?(data_module)
    data_module.service_name
  else
    data_module
  end
end
load(data_module, request, *loaders) click to toggle source

Actual load method executed on a Loader instance. Note that the result is NOT update according to the request’s return type, i.e. the result could be an Array even though a Hash is expected!

# File services.rb, line 396
def load data_module, request, *loaders

  # Skip loader, if it is not enabled
  return load_from_next_loader(data_module, request, *loaders) unless enabled?

  # Handle redirect request, if necessary
  return get_redirect(data_module, request, *loaders) if request.redirect?

  # Get loader specific result
  result = get(data_module, request)

  if PIM.is_hash?(result)

    # Result is a Hash with entries per key, so determine the missing keys to load from the next loaders
    missing_keys = request.keys - result.keys

  elsif PIM.is_array?(result)

    # Result is an Array of keys, so no additional loading is necessary
    return result

  else

    # Nothing was found, so get the result from the next loader
    missing_keys = nil

  end

  # Get and merge the missing result from next loader
  if missing_keys.nil? or not missing_keys.empty?

    # Create a new request, if necessary
    if PIM.is_array?(missing_keys) and missing_keys.to_set != request.keys.to_set
      request = request.copy(keys: missing_keys)
    end

    missing_result = load_from_next_loader(data_module, request, *loaders)
    unless missing_result.nil?

      # Cache missing result
      put(data_module, request, missing_result)

      # Merge missing Hash result, if possible, otherwise directly use as result
      if PIM.is_hash?(missing_result)

        if result.nil?
          result = missing_result
        elsif PIM.is_hash?(result)
          result = result.merge(missing_result)
        end

      elsif PIM.is_array?(missing_result)

        # Directly use the missing result as result
        result = missing_result

      end

    end

  end

  return result
end
load_from_next_loader(data_module, request, *loaders) click to toggle source

Default implementation to load result from the next loader, unless no next loader should be used.

# File services.rb, line 470
def load_from_next_loader data_module, request, *loaders
  return nil unless use_next_loader?(data_module)
  Loader.load_from_next_loader(data_module, request, *loaders)
end
put(data_module, request, result) click to toggle source

Implement in subclass

# File services.rb, line 495
def put data_module, request, result
end
put_into_repository(repository, request, result) click to toggle source

Helper method for structured key-value repositories to put the result into a “repository”.

# File services.rb, line 568
def put_into_repository repository, request, result

  # Only put result into repository if it was not marked as "cached" already
  return if Loader.is_cached?(result)

  # Get or create the base repository
  base_keys = get_base_keys(request)
  base_keys.each do |base_key|
    repository[base_key] ||= {}
    repository = repository[base_key]
  end

  # If result is an Array, cache it using the 'ALL' key
  if PIM.is_array?(result) and request.actual_keys.empty?

    repository[nil] = result

  elsif PIM.is_hash?(result) and request.return_type == Hash

    # If no keys were specified in the actual request,
    # and the 'ALL' key was not cached yet,
    # then the result is supposed to include ALL values.
    # In this case, cache all keys using the 'ALL' key.
    if request.actual_keys.empty? and repository[nil].nil?
      repository[nil] = result.keys
    end

    # Add result to repository
    result.each_pair do |key, value|
      repository[key] = value
    end

  end

end
use_next_loader?(data_module) click to toggle source

Override in subclass

# File services.rb, line 477
def use_next_loader? data_module
  true
end