class LUSI::API::Core::Lookup::LookupService

Collects a number of lookup tables into a single service

Constants

SERVICES

Configuration for lookup services The structure is: {

service: {
    available: include this service in the list of available services if true
    class: the LUSI API class returned by the lookup table (default: LUSI::API::Core::Code)
    create: create method name
    creates: the list of services created by this service
    depends: the list of services this service depends on
    load: load method name
    params: the LUSI API class #get_instance parameters
}

}

The available option, if specifies, dictates whether the service is included in the list of available services. The default is true.

The class option, if specified, is the Class instance of the object class stored in the lookup table. If no class is specified, the default is LUSI::API::Core::Code

The create option, if specified, is a symbol (method name on the LookupService instance) or callable. The create method should accept an arbitrary parameter list (method(*params)) and return a configured lookup table instance or functional equivalent. If no create method is specified, the default is to create a LookupTable instance as follows:

LUSILookupTable.new(@api, *params, loadable: true)

where params is the list from the params option (see below)

The creates option, if specified, is a list of services created by this service. This allows a single service definition to create multiple related lookup services which can be iterated in the list of available services.

The depends option, if specified, specifies a list of lookup services on which the current lookup service depends. These services are automatically loaded before the current lookup service.

The load option, if specified, is a symbol (method name on the LookupService instance) or callable. The load method should accepts two parameters: If no load method is specified, the default is to call the lookup table's load method.

The params option specifies the parameters to the create method or LookupTable constructor as a list:

[ lusi-api-url-path, lusi-api-endpoint, lusi-api-method, xml-root, result-class ]

Public Class Methods

new(api = nil, **services) click to toggle source

Initialises a new LookupService instance @param api [LUSI::API::Core::API] the LUSI API instance @param (see load) @return [void]

# File lib/lusi_api/core/lookup.rb, line 356
def initialize(api = nil, **services)
  @api = api
  clear
  load(**services) unless services.nil? || services.empty?
end

Public Instance Methods

clear() click to toggle source

Clears all lookup tables from the LookupService instance

# File lib/lusi_api/core/lookup.rb, line 363
def clear
  @lookups = {}
  @organisation = nil
end
each() { |service, lookup| ... } click to toggle source

Iterates over each lookup table @yield [service, lookup_table] passes the service name and corresponding lookup table to the block @yieldparam service [Symbol] the service name @yieldparam lookup [LUSI::API::Core::Lookup::LookupTable] the lookup table for the service @yieldreturn [void]

# File lib/lusi_api/core/lookup.rb, line 373
def each
  @lookups.each { |service, lookup| yield(service, lookup) }
end
has?(*services) click to toggle source

Returns true if all specified services are defined Parameters are the service names to be checked @return [Boolean] true if all services are definied, false if any service is undefined

# File lib/lusi_api/core/lookup.rb, line 380
def has?(*services)
  services.each { |service| return false unless @lookups.include?(service) }
  true
end
length(service = nil) click to toggle source

Returns the number of configured lookup tables @param service [Symbol, nil] the service to check

if present, return the number of entries in the specified lookup table, otherwise return the number of
lookup tables

@return [Integer] the number of configured lookup tables (if service is unspecified) or the number of

entries in the specified lookup table. If an invalid service is specified, 0 is returned.
# File lib/lusi_api/core/lookup.rb, line 391
def length(service = nil)
  if service
    lookup = @lookups[service]
    lookup ? lookup.length : 0
  else
    @lookups.length
  end
end
load(**services) click to toggle source

Loads specified lookup services, or all services if none are specified. Each named parameter specifies a configuration for the lookup service: service: config False parameter values cause that service to be ignored. @return [void]

# File lib/lusi_api/core/lookup.rb, line 404
def load(**services)

  # If no services are specified, load all services with default configuration
  if services.nil? || services.empty?
    services = {}
    SERVICES.each_key { |key| services[key] = true }
  end

  # Create the services
  services.each do |service, config|
    # Ignore invalid and unconfigured services
    create_lookup_service(service, config, services) if config && SERVICES.has_key?(service)
  end

end
lookup(service, key, default = nil) click to toggle source

Fetches a key from the specified lookup table @param service [Symbol] the lookup table to use @param key [any] the key to search for @param default [any] the default value if the lookup fails @return [Object] the value corresponding to the key

# File lib/lusi_api/core/lookup.rb, line 425
def lookup(service, key, default = nil)
  lookup_method = get_callable(service, :lookup)
  if lookup_method
    lookup_method.call(service, key, default)
  else
    lookup = @lookups[service]
    if lookup.is_a?(Hash)
      lookup[key]
    elsif lookup.is_a?(Method) || lookup.is_a?(Proc)
      lookup.call(service, key, default)
    else
      default
    end
  end
end
service(service) click to toggle source

Returns the specified lookup table @param service [Symbol] the lookup table to return @return [LUSI::API::Core::Lookup::LookupTable] the lookup table

# File lib/lusi_api/core/lookup.rb, line 444
def service(service)
  @lookups[service]
end
services(all = false) { |service| ... } click to toggle source

Returns a list of configured services @param all [Boolean] if true, returns all available services; if false, returns only configured services @yield [service] Passes the service name to the block @yieldparam service [Symbol] the service name

# File lib/lusi_api/core/lookup.rb, line 452
def services(all = false)
  if all
    # Return all services defined in SERVICES
    return @@services if @@services
    @@services = []
    SERVICES.each do |service, config|
      if config.fetch(:available, true)
        @@services.push(service)
        yield(service) if block_given?
      end
      config.fetch(:creates, []).each do |created|
        @@services.push(created)
        yield(created) if block_given?
      end
    end
    @@services
  else
    # Return all services configured in @lookups
    result = @lookups.keys
    result.each { |service| yield(service) } if block_given?
    result
  end
end

Protected Instance Methods

create_lookup(service, config, services, *params) click to toggle source

Creates a lookup table @param service [Symbol] the lookup service being created @param config [any] the lookup service configuration @param services [Hash<Symbol, any>] the configuration hash for all lookup services params is the list of parameters from the service definition in SERVICES @return [void]

# File lib/lusi_api/core/lookup.rb, line 500
def create_lookup(service, config, services, *params)
  # Create the lookup table
  result_class = SERVICES[service].fetch(:class, LUSI::API::Core::Code)
  lookup = LUSILookupTable.new(@api, result_class, *params, loadable: true)
  # Load the lookup table
  begin
    # Load dependencies
    load_dependencies(service, services) if SERVICES[service][:depends]
    # Load the table
    load_lookup(service, config, lookup)
    # Add the lookup table to the service if successful
    @lookups[service] = lookup
  rescue APIPermissionError => e
    puts("Permission denied for #{service}")
  end
end
create_lookup_service(service, config, services) click to toggle source

Creates a lookup service

  • the create method is responsible for loading the table

@param service [Symbol] the lookup service being created @param config [any] the lookup service configuration @param services [Hash<Symbol, any>] the configuration hash for all lookup services @return [void]

# File lib/lusi_api/core/lookup.rb, line 484
def create_lookup_service(service, config, services)
  create_method = get_callable(service, :create)
  params = SERVICES[service][:params] || []
  if create_method
    lookup = create_method.call(service, config, services, *params)
  else
    lookup = create_lookup(service, config, services, *params)
  end
end
create_organisation(service, config, services, *params) click to toggle source

Creates organisation lookups

@param service [Symbol] the lookup service being created @param config [any] the lookup service configuration @param services [Hash<Symbol, any>] the configuration hash for all lookup services params is the list of parameters from the service definition in SERVICES @return [void]

# File lib/lusi_api/core/lookup.rb, line 524
def create_organisation(service, config, services, *params)
  # Create and load the organisation structure
  @organisation = LUSI::API::Organisation::Organisation.new
  @organisation.load(@api)
  # Create lookups for each level of the organisation
  @organisation.each_unit_type do |unit_type|
    @lookups[unit_type] = Proc.new do |service, key, default|
      @organisation.get(key, unit_type)
    end
  end
end
get_callable(service, type) click to toggle source

Gets a method or proc of the LookupService instance @param service [Symbol] the lookup service @param type [Symbol] the type of method (:create | :load | :lookup) @return [Method, Proc] the corresponding method or proc, or nil if no method is found or an invalid

parameter is passed
# File lib/lusi_api/core/lookup.rb, line 541
def get_callable(service, type)
  callable = SERVICES[service] ? SERVICES[service][type] : nil
  case
    when callable.nil?
      nil
    when callable.is_a?(Symbol) || callable.is_a?(String)
      # callable refers to a method on this LookupService instance
      method(callable.to_sym)
    when callable.is_a?(Method) || callable.is_a?(Proc)
      # callable is already a callable object
      callable
    else
      nil
  end
end
load_dependencies(service, services) click to toggle source

Loads service dependencies @param service [Symbol] the lookup service being configured @param services [Hash<Symbol, any>] the configuration hash for all lookup services @return [void]

# File lib/lusi_api/core/lookup.rb, line 561
def load_dependencies(service, services)
  depends = SERVICES[service][:depends]
  depends.each do |depend|
    # Skip if the dependency already exists
    continue if @lookups[depend]
    # Get the config for the dependency, or use the default configuration if unspecified
    config = services[depend] || true
    # Create the lookup service if it doesn't already exist
    create_lookup_service(depend, config, services)
  end
end
load_lookup(service, config, lookup) click to toggle source

Loads a lookup table @param service [Symbol] the lookup service being configured @param config [any] the lookup service configuration @param lookup [LUSILookupTable] the lookup table to be loaded @return [LUSILookupTable] the lookup table

# File lib/lusi_api/core/lookup.rb, line 578
def load_lookup(service, config, lookup)
  load_method = get_callable(service, :load)
  if load_method
    # Call the specified load method
    load_method.call(service, config, lookup)
  else
    # Call the lookup table's load method
    # - pass this LookupService as the lookup service for object resolution
    lookup.load(false, self)
  end
  lookup
end
load_weeks(service, config, lookup) click to toggle source

Loads the academic weeks lookup table @param service [Symbol] the lookup service @param config [Array<String>] the list of year identity codes to load weeks for (default is all available weeks) @param lookup [LUSILookupTable] the lookup table being loaded @return [LUSILookupTable] the lookup table

# File lib/lusi_api/core/lookup.rb, line 596
def load_weeks(service, config, lookup)
  if config.is_a?(Array) && !config.empty?
    # Load weeks for each specified year (note: clear = false to accumulate results)
    config.each { |year_identity| lookup.load(false, self, year_identity: year_identity) }
  elsif config
    # Load all weeks
    lookup.load(false, self)
  end
  lookup
end