class InventoryRefresh::InventoryObject

Attributes

data[R]
id[RW]
inventory_collection[R]
object[RW]
reference[R]

Public Class Methods

add_attributes(inventory_object_attributes) click to toggle source

Adds setters and getters based on :inventory_object_attributes kwarg passed into InventoryCollection Methods already defined should not be redefined (causes unexpected behaviour)

@param inventory_object_attributes [Array<Symbol>]

# File lib/inventory_refresh/inventory_object.rb, line 139
def self.add_attributes(inventory_object_attributes)
  defined_methods = InventoryRefresh::InventoryObject.instance_methods(false)

  inventory_object_attributes.each do |attr|
    unless defined_methods.include?("#{attr}=".to_sym)
      define_method("#{attr}=") do |value|
        data[attr] = value
      end
    end

    unless defined_methods.include?(attr.to_sym)
      define_method(attr) do
        data[attr]
      end
    end
  end
end
allowed?(inventory_collection_scope, key) click to toggle source

Return true if the attribute is allowed to be saved into the DB

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

attribute

@param key [Symbol] attribute name @return true if the attribute is allowed to be saved into the DB

# File lib/inventory_refresh/inventory_object.rb, line 163
def self.allowed?(inventory_collection_scope, key)
  foreign_to_association = (inventory_collection_scope.foreign_key_to_association_mapping[key] ||
    inventory_collection_scope.foreign_type_to_association_mapping[key])

  return false if inventory_collection_scope.attributes_blacklist.present? &&
    (inventory_collection_scope.attributes_blacklist.include?(key) ||
      (foreign_to_association && inventory_collection_scope.attributes_blacklist.include?(foreign_to_association)))

  return false if inventory_collection_scope.attributes_whitelist.present? &&
    (!inventory_collection_scope.attributes_whitelist.include?(key) &&
      (!foreign_to_association || (foreign_to_association && inventory_collection_scope.attributes_whitelist.include?(foreign_to_association))))

  true
end
attributes_with_keys(data, inventory_collection_scope = nil, all_attribute_keys = [], inventory_object = nil) click to toggle source

Transforms InventoryObject object data into hash format with keys that are column names and resolves correct values of the foreign keys (even the polymorphic ones)

@param data [Array<Object>] Array of objects that we want to map to DB table columns @param inventory_collection_scope [InventoryRefresh::InventoryCollection] parent InventoryCollection object @param all_attribute_keys [Array<Symbol>] Attribute keys we will modify based on object's data @param inventory_object [InventoryRefresh::InventoryObject] InventoryObject object owning these attributes @return [Hash] Data in DB format

# File lib/inventory_refresh/inventory_object.rb, line 50
def self.attributes_with_keys(data, inventory_collection_scope = nil, all_attribute_keys = [], inventory_object = nil)
  # We should explicitly pass a scope, since the inventory_object can be mapped to more InventoryCollections with
  # different blacklist and whitelist. The generic code always passes a scope.
  inventory_collection_scope ||= inventory_collection

  attributes_for_saving = {}
  # First transform the values
  data.each do |key, value|
    if !allowed?(inventory_collection_scope, key)
      next
    elsif loadable?(value) || inventory_collection_scope.association_to_foreign_key_mapping[key]
      # Lets fill also the original data, so other InventoryObject referring to this attribute gets the right
      # result
      data[key] = value.load(inventory_object, key) if value.respond_to?(:load)
      if (foreign_key = inventory_collection_scope.association_to_foreign_key_mapping[key])
        # We have an association to fill, lets fill also the :key, cause some other InventoryObject can refer to it
        record_id = data[key].try(:id)
        foreign_key_to_sym = foreign_key.to_sym
        attributes_for_saving[foreign_key_to_sym] = record_id
        all_attribute_keys << foreign_key_to_sym
        if (foreign_type = inventory_collection_scope.association_to_foreign_type_mapping[key])
          # If we have a polymorphic association, we need to also fill a base class name, but we want to nullify it
          # if record_id is missing
          base_class = data[key].try(:base_class_name) || data[key].class.try(:base_class).try(:name)
          foreign_type_to_sym = foreign_type.to_sym
          attributes_for_saving[foreign_type_to_sym] = record_id ? base_class : nil
          all_attribute_keys << foreign_type_to_sym
        end
      else
        # We have a normal attribute to fill
        attributes_for_saving[key] = data[key]
        all_attribute_keys << key
      end
    else
      attributes_for_saving[key] = value
      all_attribute_keys << key
    end
  end

  attributes_for_saving
end
loadable?(value) click to toggle source

Return true if the object is loadable, which we determine by a list of loadable classes.

@param value [Object] object we test @return true if the object is loadable

# File lib/inventory_refresh/inventory_object.rb, line 182
def self.loadable?(value)
  value.kind_of?(::InventoryRefresh::InventoryObjectLazy) || value.kind_of?(::InventoryRefresh::InventoryObject) ||
    value.kind_of?(::InventoryRefresh::ApplicationRecordReference)
end
new(inventory_collection, data) click to toggle source

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

InventoryObject

@param data [Hash] Data of the InventoryObject object

# File lib/inventory_refresh/inventory_object.rb, line 15
def initialize(inventory_collection, data)
  @inventory_collection     = inventory_collection
  @data                     = data
  @object                   = nil
  @id                       = nil
  @reference                = inventory_collection.build_reference(data)
end

Public Instance Methods

assign_attributes(attributes) click to toggle source

Given hash of attributes, we assign them to InventoryObject object using its public writers

@param attributes [Hash] attributes we want to assign @return [InventoryRefresh::InventoryObject] self

# File lib/inventory_refresh/inventory_object.rb, line 96
def assign_attributes(attributes)
  attributes.each do |k, v|
    # We don't want timestamps or resource versions to be overwritten here, since those are driving the conditions
    next if %i(resource_timestamps resource_timestamps_max resource_timestamp).include?(k)
    next if %i(resource_counters resource_counters_max resource_counter).include?(k)

    if data[:resource_timestamp] && attributes[:resource_timestamp]
      assign_only_newest(:resource_timestamp, :resource_timestamps, attributes, data, k, v)
    elsif data[:resource_counter] && attributes[:resource_counter]
      assign_only_newest(:resource_counter, :resource_counters, attributes, data, k, v)
    else
      public_send("#{k}=", v)
    end
  end

  if attributes[:resource_timestamp]
    assign_full_row_version_attr(:resource_timestamp, attributes, data)
  elsif attributes[:resource_counter]
    assign_full_row_version_attr(:resource_counter, attributes, data)
  end

  self
end
dependency?() click to toggle source

@return [TrueClass] InventoryObject object is always a dependency

# File lib/inventory_refresh/inventory_object.rb, line 131
def dependency?
  true
end
inspect() click to toggle source

@return [String] string format for nice logging

# File lib/inventory_refresh/inventory_object.rb, line 126
def inspect
  "InventoryObject:('#{manager_uuid}', #{inventory_collection})"
end
key() click to toggle source
# File lib/inventory_refresh/inventory_object.rb, line 38
def key
  nil
end
load(*_args) click to toggle source

@return [InventoryRefresh::InventoryObject] returns self

# File lib/inventory_refresh/inventory_object.rb, line 34
def load(*_args)
  self
end
manager_uuid() click to toggle source

@return [String] stringified reference

# File lib/inventory_refresh/inventory_object.rb, line 24
def manager_uuid
  reference.stringified_reference
end
to_s() click to toggle source

@return [String] stringified UUID

# File lib/inventory_refresh/inventory_object.rb, line 121
def to_s
  manager_uuid
end
uuid() click to toggle source

@return [Hash] hash reference having :manager_ref keys, which can uniquely identity entity under a manager

# File lib/inventory_refresh/inventory_object.rb, line 29
def uuid
  reference.full_reference.slice(*reference.keys).stringify_keys!
end

Private Instance Methods

allowed?(inventory_collection_scope, key) click to toggle source

Return true if the attribute is allowed to be saved into the DB

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

attribute

@param key [Symbol] attribute name @return true if the attribute is allowed to be saved into the DB

# File lib/inventory_refresh/inventory_object.rb, line 263
def allowed?(inventory_collection_scope, key)
  self.class.allowed?(inventory_collection_scope, key)
end
assign_full_row_version_attr(full_row_version_attr, attributes, data) click to toggle source

Assigns attribute representing version of the whole row

@param full_row_version_attr [Symbol] Attr name for full rows, allowed values are

[:resource_timestamp, :resource_counter]

@param attributes [Hash] New attributes we are assigning @param data [Hash] Existing attributes of the InventoryObject

# File lib/inventory_refresh/inventory_object.rb, line 237
def assign_full_row_version_attr(full_row_version_attr, attributes, data)
  if attributes[full_row_version_attr] && data[full_row_version_attr]
    # If both timestamps are present, store the bigger one
    data[full_row_version_attr] = attributes[full_row_version_attr] if attributes[full_row_version_attr] > data[full_row_version_attr]
  elsif attributes[full_row_version_attr] && !data[full_row_version_attr]
    # We are assigning timestamp that was missing
    data[full_row_version_attr] = attributes[full_row_version_attr]
  end
end
assign_only_newest(full_row_version_attr, partial_row_version_attr, attributes, data, k, v) click to toggle source

Assigns value based on the version attributes. If versions are specified, it asigns attribute only if it's newer than existing attribute.

@param full_row_version_attr [Symbol] Attr name for full rows, allowed values are

[:resource_timestamp, :resource_counter]

@param partial_row_version_attr [Symbol] Attr name for partial rows, allowed values are

[:resource_timestamps, :resource_counters]

@param attributes [Hash] New attributes we are assigning @param data [Hash] Existing attributes of the InventoryObject @param k [Symbol] Name of the attribute we are assigning @param v [Object] Value of the attribute we are assigning

# File lib/inventory_refresh/inventory_object.rb, line 200
def assign_only_newest(full_row_version_attr, partial_row_version_attr, attributes, data, k, v)
  # If timestamps are in play, we will set only attributes that are newer
  specific_attr_timestamp = attributes[partial_row_version_attr].try(:[], k)
  specific_data_timestamp = data[partial_row_version_attr].try(:[], k)

  assign = if !specific_attr_timestamp
             # Data have no timestamp, we will ignore the check
             true
           elsif specific_attr_timestamp && !specific_data_timestamp
             # Data specific timestamp is nil and we have new specific timestamp
             if data.key?(k)
               if attributes[full_row_version_attr] >= data[full_row_version_attr]
                 # We can save if the full timestamp is bigger, if the data already contains the attribute
                 true
               end
             else
               # Data do not contain the attribute, so we are saving the newest
               true
             end
             true
           elsif specific_attr_timestamp > specific_data_timestamp
             # both partial timestamps are there, newer must be bigger
             true
           end

  if assign
    public_send("#{k}=", v) # Attribute is newer than current one, lets use it
    (data[partial_row_version_attr] ||= {})[k] = specific_attr_timestamp if specific_attr_timestamp # and set the latest timestamp
  end
end
association?(inventory_collection_scope, key) click to toggle source

Return true passed key representing a getter is an association

@param inventory_collection_scope [InventoryRefresh::InventoryCollection] @param key [Symbol] key representing getter @return [Boolean] true if the passed key points to association

# File lib/inventory_refresh/inventory_object.rb, line 252
def association?(inventory_collection_scope, key)
  # Is the key an association on inventory_collection_scope model class?
  !inventory_collection_scope.association_to_foreign_key_mapping[key].nil?
end
loadable?(value) click to toggle source

Return true if the object is loadable, which we determine by a list of loadable classes.

@param value [Object] object we test @return true if the object is loadable

# File lib/inventory_refresh/inventory_object.rb, line 271
def loadable?(value)
  self.class.loadable?(value)
end