Class: VirtualBox::AbstractModel Abstract
- Inherits:
-
Object
- Object
- VirtualBox::AbstractModel
- Includes:
- Attributable, Dirty, InterfaceAttributes, Relatable, Validatable, Logger
- Defined in:
- lib/virtualbox/abstract_model.rb,
lib/virtualbox/abstract_model/dirty.rb,
lib/virtualbox/abstract_model/relatable.rb,
lib/virtualbox/abstract_model/validatable.rb,
lib/virtualbox/abstract_model/attributable.rb,
lib/virtualbox/abstract_model/version_matcher.rb,
lib/virtualbox/abstract_model/interface_attributes.rb
Overview
AbstractModel is the base class used for most of virtualbox’s classes. It provides convenient ActiveRecord-style model behavior to subclasses.
Direct Known Subclasses
Appliance, AudioAdapter, BIOS, CPU, DHCPServer, ForwardedPort, Global, HWVirtualization, Host, HostNetworkInterface, Media, Medium, MediumAttachment, NATEngine, NATForwardedPort, NetworkAdapter, SharedFolder, Snapshot, StorageController, SystemProperties, USBController, USBDeviceFilter, VM, VRDEServer, VirtualSystemDescription
Defined Under Namespace
Modules: Attributable, Dirty, InterfaceAttributes, Relatable, Validatable, VersionMatcher
Class Method Summary collapse
-
.errors_for_relationship(caller, data) ⇒ Object
Default errors for relationship implementation, since this is a pretty stable method.
- .reload! ⇒ Object
-
.reload? ⇒ Boolean
Returns whether or not the class should be reloaded.
- .reloaded! ⇒ Object
Instance Method Summary collapse
-
#destroy(*args) ⇒ Object
Destroys the model.
-
#errors ⇒ Object
Returns the errors for a model.
-
#existing_record! ⇒ Object
Explicitly sets the model to not be a new record.
-
#inspect ⇒ Object
Creates a human-readable format for this model.
-
#lazy_attribute?(*args) ⇒ Boolean
Overriding Attributable#lazy_attribute? to always return false for new records, since new records shouldn’t load lazy data.
-
#lazy_relationship?(*args) ⇒ Boolean
Overriding Relatable#lazy_relationship? to always return false for new records, since new records shouldn’t load lazy data.
-
#new_record! ⇒ Object
Explicitly resets the model to a new record.
-
#new_record? ⇒ Boolean
Returns a boolean denoting if the record is new or existing.
-
#parent_machine ⇒ VM
Gets the root machine of an AbstractModel by traversing a ‘parent` attribute until it reaches a type of VM.
-
#populate_attributes(attribs, opts = {}) ⇒ Object
Sets the initial attributes from a hash.
-
#populate_relationship(name, data) ⇒ Object
Populates a single relationship with the given data.
-
#populate_relationships(data) ⇒ Object
Loads and populates the relationships with the given data.
-
#reload! ⇒ Object
Signals to the class that it should be reloaded.
-
#save(*args) ⇒ Object
Saves the model attributes and relationships.
-
#save!(*args) ⇒ Object
Saves the model and raises an Exceptions::ValidationFailedException if the model is invalid, instead of returning false.
-
#save_attribute(key, value, *args) ⇒ Object
Saves a single attribute of the model.
-
#save_changed_interface_attributes(interface) ⇒ Object
Saves only changed interface attributes.
-
#save_interface_attribute(key, interface) ⇒ Object
Overrides InterfaceAttributes#save_interface_attribute to clear the dirty state of the attribute.
-
#set_relationship(key, value) ⇒ Object
Overwrites Relatable#set_relationship to set the dirty state of the relationship.
-
#validate(*args) ⇒ Object
Validates the model and relationships.
-
#write_attribute(name, value) ⇒ Object
Overwrites Attributable#write_attribute to set the dirty state of the written attribute.
Methods included from Validatable
#__validates_extract_options, #add_error, #clear_errors, #errors_on, #full_error_messages, #valid?, #validates_format_of, #validates_inclusion_of, #validates_numericality_of, #validates_presence_of
Methods included from Relatable
#destroy_relationship, #destroy_relationships, #has_relationship?, included, #loaded_relationship?, #read_relationship, #relationship_class, #relationship_data, #save_relationship, #save_relationships
Methods included from VersionMatcher
#assert_version_match, #split_version, #version_match?
Methods included from Dirty
#changed?, #changes, #clear_dirty!, #ignore_dirty, #method_missing, #set_dirty!
Methods included from InterfaceAttributes
#load_interface_attribute, #load_interface_attributes, #save_interface_attributes, #spec_to_proc
Methods included from Attributable
#attributes, #has_attribute?, included, #loaded_attribute?, #read_attribute, #readonly_attribute?
Methods included from Logger
included, #logger, #logger_output=
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class VirtualBox::AbstractModel::Dirty
Class Method Details
.errors_for_relationship(caller, data) ⇒ Object
Default errors for relationship implementation, since this is a pretty stable method.
41 42 43 44 |
# File 'lib/virtualbox/abstract_model.rb', line 41 def errors_for_relationship(caller, data) return data.errors if data.respond_to?(:errors) nil end |
.reload! ⇒ Object
31 32 33 |
# File 'lib/virtualbox/abstract_model.rb', line 31 def reload! @_reload = true end |
.reload? ⇒ Boolean
Returns whether or not the class should be reloaded.
27 28 29 |
# File 'lib/virtualbox/abstract_model.rb', line 27 def reload? !!@_reload end |
.reloaded! ⇒ Object
35 36 37 |
# File 'lib/virtualbox/abstract_model.rb', line 35 def reloaded! @_reload = false end |
Instance Method Details
#destroy(*args) ⇒ Object
Destroys the model. The exact behaviour of this method is expected to be defined on the subclasses. This method on AbstractModel simply propagates the destroy to the dependent relationships. For more information on relationships, see Relatable.
237 238 239 240 241 242 |
# File 'lib/virtualbox/abstract_model.rb', line 237 def destroy(*args) # Destroy dependent relationships self.class.relationships.each do |name, | destroy_relationship(name, *args) if [:dependent] == :destroy end end |
#errors ⇒ Object
Returns the errors for a model.
79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/virtualbox/abstract_model.rb', line 79 def errors self.class.relationships.inject(super) do |acc, data| name, = data if && [:klass].respond_to?(:errors_for_relationship) errors = [:klass].errors_for_relationship(self, relationship_data[name]) acc.merge!(name => errors) if errors && !errors.empty? end acc end end |
#existing_record! ⇒ Object
Explicitly sets the model to not be a new record. If you’re using this method outside of virtualbox library core, you should really be asking yourself “why?”
74 75 76 |
# File 'lib/virtualbox/abstract_model.rb', line 74 def existing_record! @new_record = false end |
#inspect ⇒ Object
Creates a human-readable format for this model. This method overrides the default ‘#<class>` syntax since this doesn’t work well for AbstractModels. Instead, it abbreviates it, instead showing all the attributes and their values, and ‘…` for relationships. For attributes which are themselves AbstractModels, it shows the class name to avoid extremely verbose inspections and infinite loops.
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/virtualbox/abstract_model.rb', line 260 def inspect values = [] self.class.attributes.each do |name, | value = read_attribute(name) value = if value.is_a?(AbstractModel) || value.is_a?(COM::AbstractInterface) || value.is_a?(Proxies::Collection) "#<#{value.class.name}>" else value.inspect end values.push("#{name.inspect}=#{value}") end self.class.relationships.each do |name, | values.push("#{name.inspect}=...") end "#<#{self.class} #{values.sort.join(", ")}>".strip end |
#lazy_attribute?(*args) ⇒ Boolean
Overriding VirtualBox::AbstractModel::Attributable#lazy_attribute? to always return false for new records, since new records shouldn’t load lazy data.
162 163 164 165 |
# File 'lib/virtualbox/abstract_model.rb', line 162 def lazy_attribute?(*args) return false if new_record? super end |
#lazy_relationship?(*args) ⇒ Boolean
Overriding VirtualBox::AbstractModel::Relatable#lazy_relationship? to always return false for new records, since new records shouldn’t load lazy data.
169 170 171 172 |
# File 'lib/virtualbox/abstract_model.rb', line 169 def lazy_relationship?(*args) return false if new_record? super end |
#new_record! ⇒ Object
Explicitly resets the model to a new record. If you’re using this method outside of virtualbox library core, you should really be asking yourself “why?”
67 68 69 |
# File 'lib/virtualbox/abstract_model.rb', line 67 def new_record! @new_record = true end |
#new_record? ⇒ Boolean
Returns a boolean denoting if the record is new or existing. This method is provided for subclasses to use to differentiate between creating a new object or saving an existing one. An example of this is HardDrive#save which will create a new hard drive if it didn’t previously exist, or save an old one if it did exist.
59 60 61 62 |
# File 'lib/virtualbox/abstract_model.rb', line 59 def new_record? new_record! if !defined?(@new_record) || @new_record.nil? @new_record end |
#parent_machine ⇒ VM
Gets the root machine of an AbstractModel by traversing a ‘parent` attribute until it reaches a type of VM.
248 249 250 251 252 |
# File 'lib/virtualbox/abstract_model.rb', line 248 def parent_machine current = parent current = current.parent while current && !current.is_a?(VM) current end |
#populate_attributes(attribs, opts = {}) ⇒ Object
Sets the initial attributes from a hash. This method is meant to be used once to initially setup the attributes. It is **not a mass-assignment** method for updating attributes.
This method does not affect dirtiness, but also does not clear it. This means that if you call populate_attributes, the same attributes that were dirty before the call will be dirty after the call (but no more and no less). This distinction is important because most subclasses of AbstractModel only save changed attributes, and ignore unchanged attributes. Attempting to change attributes through this method will cause them to not be saved, which is surely unexpected behaviour for most users.
Calling this method will also cause the model to assume that it is not a new record (see #new_record?).
189 190 191 192 193 194 195 196 197 198 |
# File 'lib/virtualbox/abstract_model.rb', line 189 def populate_attributes(attribs, opts={}) ignore_dirty do super(attribs) populate_relationships(attribs) unless opts[:ignore_relationships] end # No longer a new record existing_record! end |
#populate_relationship(name, data) ⇒ Object
Populates a single relationship with the given data.
213 214 215 216 |
# File 'lib/virtualbox/abstract_model.rb', line 213 def populate_relationship(name, data) existing_record! ignore_dirty { super } end |
#populate_relationships(data) ⇒ Object
Loads and populates the relationships with the given data. This method is meant to be used once to initially setup the relatoinships.
This methods does not affect dirtiness, but also does not clear it.
Calling this method will also cuase the model to assume that it is not a new record (see #new_record?)
207 208 209 210 |
# File 'lib/virtualbox/abstract_model.rb', line 207 def populate_relationships(data) existing_record! ignore_dirty { super } end |
#reload! ⇒ Object
Signals to the class that it should be reloaded. This simply toggles a boolean value to true. It is up to the subclass to implement functionality around it. See reload?
50 51 52 |
# File 'lib/virtualbox/abstract_model.rb', line 50 def reload! self.class.reload! end |
#save(*args) ⇒ Object
Saves the model attributes and relationships.
The method can be passed any arbitrary arguments, which are implementation specific (see VM#save, which does this).
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/virtualbox/abstract_model.rb', line 111 def save(*args) # Go through changed attributes and call save_attribute for # those only changes.each do |key, values| save_attribute(key, values[1], *args) end # Go through and only save the loaded relationships, since # only those would be modified. self.class.relationships.each do |name, | save_relationship(name, *args) end # No longer a new record @new_record = false true end |
#save!(*args) ⇒ Object
Saves the model and raises an Exceptions::ValidationFailedException if the model is invalid, instead of returning false.
132 133 134 135 |
# File 'lib/virtualbox/abstract_model.rb', line 132 def save!(*args) raise Exceptions::ValidationFailedException.new(errors.inspect) if !save(*args) true end |
#save_attribute(key, value, *args) ⇒ Object
Saves a single attribute of the model. This method on the abstract model does nothing on its own, and is expected to be overridden by any subclasses.
This method clears the dirty status of the attribute.
142 143 144 |
# File 'lib/virtualbox/abstract_model.rb', line 142 def save_attribute(key, value, *args) clear_dirty!(key) end |
#save_changed_interface_attributes(interface) ⇒ Object
Saves only changed interface attributes.
147 148 149 150 151 |
# File 'lib/virtualbox/abstract_model.rb', line 147 def save_changed_interface_attributes(interface) changes.each do |key, values| save_interface_attribute(key, interface) end end |
#save_interface_attribute(key, interface) ⇒ Object
Overrides VirtualBox::AbstractModel::InterfaceAttributes#save_interface_attribute to clear the dirty state of the attribute.
155 156 157 158 |
# File 'lib/virtualbox/abstract_model.rb', line 155 def save_interface_attribute(key, interface) super clear_dirty!(key) end |
#set_relationship(key, value) ⇒ Object
Overwrites VirtualBox::AbstractModel::Relatable#set_relationship to set the dirty state of the relationship. See VirtualBox::AbstractModel::Dirty#set_dirty! as well.
227 228 229 230 231 |
# File 'lib/virtualbox/abstract_model.rb', line 227 def set_relationship(key, value) existing = relationship_data[key] new_value = super set_dirty!(key, existing, new_value) end |
#validate(*args) ⇒ Object
Validates the model and relationships.
93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/virtualbox/abstract_model.rb', line 93 def validate(*args) # First clear all previous errors clear_errors # Then do the validations failed = false self.class.relationships.each do |name, | next unless && [:klass].respond_to?(:validate_relationship) failed = true if ![:klass].validate_relationship(self, relationship_data[name], *args) end return !failed end |
#write_attribute(name, value) ⇒ Object
Overwrites VirtualBox::AbstractModel::Attributable#write_attribute to set the dirty state of the written attribute. See VirtualBox::AbstractModel::Dirty#set_dirty! as well.
220 221 222 223 |
# File 'lib/virtualbox/abstract_model.rb', line 220 def write_attribute(name, value) set_dirty!(name, read_attribute(name), value) unless lazy_attribute?(name) && !loaded_attribute?(name) super end |