class InventoryRefresh::InventoryObjectLazy

Attributes

default[R]
inventory_collection[R]
key[R]
reference[RW]
transform_nested_lazy_finds[R]

Public Class Methods

new(inventory_collection, index_data, ref: :manager_ref, key: nil, default: nil, transform_nested_lazy_finds: false) click to toggle source

@param inventory_collection [InventoryRefresh::InventoryCollection] InventoryCollection object owning the

InventoryObject

@param index_data [Hash] data of the InventoryObject object @param ref [Symbol] reference name @param key [Symbol] key name, will be used to fetch attribute from resolved InventoryObject @param default [Object] a default value used if the :key will resolve to nil @param transform_nested_lazy_finds [Boolean] True if we want to convert all lazy objects in InventoryObject

objects and reset the Reference. TODO(lsmola) we should be able to do this automatically, then we can
remove this option
# File lib/inventory_refresh/inventory_object_lazy.rb, line 18
def initialize(inventory_collection, index_data, ref: :manager_ref, key: nil, default: nil, transform_nested_lazy_finds: false)
  @inventory_collection = inventory_collection
  @reference            = inventory_collection.build_reference(index_data, ref)
  @key                  = key
  @default              = default

  @transform_nested_lazy_finds = transform_nested_lazy_finds

  # We do not support skeletal pre-create for :key, since :key will not be available, we want to use local_db_find
  # instead.
  skeletal_precreate! unless @key
end

Public Instance Methods

association?(key) click to toggle source

@return [Boolean] true if the key is an association on inventory_collection_scope model class

# File lib/inventory_refresh/inventory_object_lazy.rb, line 72
def association?(key)
  inventory_collection.dependency_attributes.key?(key) ||
    !inventory_collection.association_to_foreign_key_mapping[key].nil?
end
dependency?() click to toggle source

return [Boolean] true if the Lazy object is causing a dependency, Lazy link is always a dependency if no :key

is provider or if it's transitive_dependency
# File lib/inventory_refresh/inventory_object_lazy.rb, line 56
def dependency?
  # If key is not set, InventoryObjectLazy is a dependency, cause it points to the record itself. Otherwise
  # InventoryObjectLazy is a dependency only if it points to an attribute which is a dependency or a relation.
  !key || transitive_dependency?
end
inspect() click to toggle source

@return [String] string format for nice logging

# File lib/inventory_refresh/inventory_object_lazy.rb, line 37
def inspect
  suffix = ""
  suffix += ", ref: #{ref}" if ref.present?
  suffix += ", key: #{key}" if key.present?
  "InventoryObjectLazy:('#{self}', #{inventory_collection}#{suffix})"
end
load(inventory_object = nil, inventory_object_key = nil) click to toggle source

@param inventory_object [InventoryRefresh::InventoryObject] InventoryObject object owning this relation @param inventory_object_key [Symbol] InventoryObject object's attribute pointing to this relation @return [InventoryRefresh::InventoryObject, Object] InventoryRefresh::InventoryObject instance or an attribute

on key
# File lib/inventory_refresh/inventory_object_lazy.rb, line 48
def load(inventory_object = nil, inventory_object_key = nil)
  transform_nested_secondary_indexes! if transform_nested_lazy_finds && nested_secondary_index?

  load_object(inventory_object, inventory_object_key)
end
to_s() click to toggle source

@return [String] stringified reference

# File lib/inventory_refresh/inventory_object_lazy.rb, line 32
def to_s
  stringified_reference
end
transform_nested_secondary_indexes!(depth = 0) click to toggle source
# File lib/inventory_refresh/inventory_object_lazy.rb, line 77
def transform_nested_secondary_indexes!(depth = 0)
  raise "Nested references are too deep!" if depth > 20

  keys.each do |x|
    attr = full_reference[x]
    next unless attr.kind_of?(InventoryRefresh::InventoryObjectLazy)
    next if attr.primary?

    if attr.nested_secondary_index?
      attr.transform_nested_secondary_indexes!(depth + 1)
    end

    full_reference[x] = full_reference[x].load
  end

  # Rebuild the reference to get the right value
  self.reference = inventory_collection.build_reference(full_reference, ref)
end
transitive_dependency?() click to toggle source

return [Boolean] true if the Lazy object is causing a transitive dependency, which happens if the :key points

to an attribute that is causing a dependency.
# File lib/inventory_refresh/inventory_object_lazy.rb, line 64
def transitive_dependency?
  # If the dependency is inventory_collection.lazy_find(:ems_ref, :key => :stack)
  # and a :stack is a relation to another object, in the InventoryObject object,
  # then this relation is considered transitive.
  key && association?(key)
end

Private Instance Methods

load_object(inventory_object = nil, inventory_object_key = nil) click to toggle source

@return [InventoryRefresh::InventoryObject, NilClass] InventoryRefresh::InventoryObject instance or nil if not found

# File lib/inventory_refresh/inventory_object_lazy.rb, line 142
def load_object(inventory_object = nil, inventory_object_key = nil)
  loaded_object = inventory_collection.find(reference)

  if inventory_object && inventory_object_key && !loaded_object && reference.loadable?
    # Object was not loaded, but the reference is pointing to something, lets return it as edge that should've
    # been loaded.
    inventory_object.inventory_collection.store_unconnected_edges(inventory_object, inventory_object_key, self)
  end

  key ? load_object_with_key(loaded_object) : loaded_object
end
load_object_with_key(loaded_object) click to toggle source

@param loaded_object [InventoryRefresh::InventoryObject, NilClass] Loaded object or nil if object wasn't found @return [Object] value found or :key or default value if the value is nil

# File lib/inventory_refresh/inventory_object_lazy.rb, line 128
def load_object_with_key(loaded_object)
  # TODO(lsmola) Log error if we are accessing path that is present in blacklist or not present in whitelist
  if loaded_object.present?
    if loaded_object.try(:data).present?
      loaded_object.data[key] || default
    else
      loaded_object.public_send(key) || default
    end
  else
    default
  end
end
skeletal_precreate!() click to toggle source

Instead of loading the reference from the DB, we'll add the skeletal InventoryObject (having manager_ref and info from the default_values) to the correct InventoryCollection. Which will either be found in the DB or created as a skeletal object. The later refresh of the object will then fill the rest of the data, while not touching the reference.

@return [InventoryRefresh::InventoryObject, NilClass] Returns pre-created InventoryObject or nil

# File lib/inventory_refresh/inventory_object_lazy.rb, line 109
def skeletal_precreate!
  # Pre-create only for strategies that will be persisting data, i.e. are not saved already
  return if saved?
  # We can only do skeletal pre-create for primary index reference, since that is needed to create DB unique index
  # and full reference must be present
  return if !primary? || full_reference.blank?

  # To avoid pre-creating invalid records all fields of a primary key must have non null value
  # TODO(lsmola) for composite keys, it's still valid to have one of the keys nil, figure out how to allow this. We
  # will need to scan the DB for NOT NULL constraint and allow it based on that. So we would move this check to
  # saving code, but this will require bigger change, since having the column nil means we will have to batch it
  # smartly, since having nil means we will need to use different unique index for the upsert/update query.
  return if keys.any? { |x| full_reference[x].nil? }

  skeletal_primary_index.build(full_reference)
end