class InventoryRefresh::InventoryObject
Attributes
Public Class Methods
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
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
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
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
@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
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
@return [TrueClass] InventoryObject
object is always a dependency
# File lib/inventory_refresh/inventory_object.rb, line 131 def dependency? true end
@return [String] string format for nice logging
# File lib/inventory_refresh/inventory_object.rb, line 126 def inspect "InventoryObject:('#{manager_uuid}', #{inventory_collection})" end
# File lib/inventory_refresh/inventory_object.rb, line 38 def key nil end
@return [InventoryRefresh::InventoryObject] returns self
# File lib/inventory_refresh/inventory_object.rb, line 34 def load(*_args) self end
@return [String] stringified reference
# File lib/inventory_refresh/inventory_object.rb, line 24 def manager_uuid reference.stringified_reference end
@return [String] stringified UUID
# File lib/inventory_refresh/inventory_object.rb, line 121 def to_s manager_uuid end
@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
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
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
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
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
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