module HasAttributes
HasAttributes
allows objects to have arbitrary attributes associated with it.
Public Instance Methods
# File lib/geoengineer/utils/has_attributes.rb, line 14 def [](key) retrieve_attribute(key.to_s) end
# File lib/geoengineer/utils/has_attributes.rb, line 18 def []=(key, val) assign_attribute(key.to_s, [val]) end
# File lib/geoengineer/utils/has_attributes.rb, line 30 def assign_attribute(name, args) # this is a setter name = name[0...-1] if name.end_with?"=" val = args.length == 1 ? args[0] : args attribute_procs[name] = val if val.is_a?(Proc) attributes[name] = val end
# File lib/geoengineer/utils/has_attributes.rb, line 26 def assign_block(name, *args, &block) throw "#{self.class.inspect} cannot handle block" end
# File lib/geoengineer/utils/has_attributes.rb, line 60 def attribute_missing(name) nil end
Contains the procs used to calculate attributes
# File lib/geoengineer/utils/has_attributes.rb, line 10 def attribute_procs @_procs ||= {} end
# File lib/geoengineer/utils/has_attributes.rb, line 5 def attributes @_attributes ||= {} end
# File lib/geoengineer/utils/has_attributes.rb, line 22 def delete(key) attributes.delete(key.to_s) end
# File lib/geoengineer/utils/has_attributes.rb, line 55 def eager_load_attributes attribute_procs.each { |name, function| attributes[name] = function.call() } self end
This method allows attributes to be defined on an instance without explicitly defining which attributes are allowed
The flow is:
-
If the method receives a block, it will pass it to the `assign_block` method to be handled. By default this method will throw an error, but can be overridden by the class.
-
If the method has one or more argument it will assume it is a setter and store the argument as an attribute.
-
If the method has no arguments it will assume it is a getter and retrieve the value. If the retrieved value is a `Proc` it will execute it and store the returned value, this will allow for caching expensive calls and only calling if requested
# File lib/geoengineer/utils/has_attributes.rb, line 75 def method_missing(name, *args, &block) name = name.to_s if block_given? # A class can override a assign_block(name, *args, &block) elsif args.length >= 1 assign_attribute(name, args) elsif args.empty? retrieve_attribute(name) end end
For any value that has been lazily calculated, recalculate it
# File lib/geoengineer/utils/has_attributes.rb, line 50 def reset_attributes attribute_procs.each { |name, function| attributes[name] = function } self end
# File lib/geoengineer/utils/has_attributes.rb, line 38 def retrieve_attribute(name) # this is a getter val = if attributes.key?(name) attributes[name] else attribute_missing(name) end return val unless val.is_a?(Proc) attributes[name] = val.call() # cache the value to override the Proc end
# File lib/geoengineer/utils/has_attributes.rb, line 101 def terraform_attribute_ref(k) v = retrieve_attribute(k) if v.is_a? GeoEngineer::Resource # convert Resource to reference for terraform v.to_ref elsif v.is_a? Array # map resources if attribute is an array v.map { |vi| vi.is_a?(GeoEngineer::Resource) ? vi.to_ref : vi } else v end end
This method creates a set of attributes for terraform to consume
# File lib/geoengineer/utils/has_attributes.rb, line 93 def terraform_attributes attributes .select { |k, v| !k.nil? && !k.start_with?('_') } .map { |k, v| [k, terraform_attribute_ref(k)] } .select { |k, v| !v.nil? } .to_h end
must override because of Object#timeout
# File lib/geoengineer/utils/has_attributes.rb, line 88 def timeout(*args) method_missing(:timeout, *args) end